rjeczalik / notify

File system event notification library on steroids.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

rm dir actions triggered two remove event

JK-97 opened this issue · comments

mycode


func FileListener(path string) {
	c := make(chan notify.EventInfo, 1)
	if err := notify.Watch(path, c, notify.Create, notify.InMovedFrom, notify.InModify, notify.InMovedTo, notify.Remove); err != nil {
		log.Error(err)
	}
	defer notify.Stop(c)
	moves := make(map[uint32]struct {
		From string
		To   string
	})

	for ei := range c {
		cookie := ei.Sys().(*unix.InotifyEvent).Cookie
		info := moves[cookie]
		switch ei.Event() {
		case notify.InMovedFrom:
			info.From = ei.Path()
			//log.Warn("InMovedFrom", ei.Path())
		case notify.InMovedTo:
			info.To = ei.Path()
			//log.Warn("InMovedTo", ei.Path())
		case notify.Create:
			if (ei.Path() == "/edge/synctools.zip") {
				log.Info("has detecd the sysctools package,")
				utils.Unzip("/edge/synctools.zip", "/edge/mnt")
				log.Info("has unzip the systools,")
			}
			log.Info("create", ei.Path())
		case notify.Remove:
			log.Warn("remove", ei.Path())
		case notify.InModify:
			log.Warn("modify", ei.Path())

		}
		moves[cookie] = info

		if cookie != 0 && info.From != "" && info.To != "" {
			log.Warn("File:", info.From, "was renamed to", info.To)
			delete(moves, cookie)
		}
	}
}

my watchpath is /edge/...

when i rm aa dir
but the log is:
INFO[0018] create/edge/mnt/aa
WARN[0020] remove/edge/mnt/aa
WARN[0020] remove/edge/mnt/aa

@JK-97 What OS is that? Can you build your application with debug tag and run it again?

@JK-97 What OS is that? Can you build your application with debug tag and run it again?

my os is ubuntu 16.04
is that resulting in i use “rm -r xxx”? because it is recursive?

@JK-97 Yes and no, if you rm -rf then you're going to receive remove events for each deleted dir and file, but you shouldn't receive duplicated events on the same channel if you registered the channel only once.

The debug output I mentioned above could shed some light what's happening.

commented

Seams to be a bug with the inotify implementation:

package main
import (
        "github.com/rjeczalik/notify"
        "github.com/davecgh/go-spew/spew"
)

func main() {
        events := make(chan notify.EventInfo, 10)
        if err := notify.Watch("/tmp/test/...", events, notify.Remove); err != nil {
                panic(err.Error())
        }

        for event := range events {
                spew.Dump(event)
        }
}

action:

/tmp/test/$ mkdir a
/tmp/test/$ rmdir a

log:

2023/01/18 10:39:11.144748 [D] dispatching notify.Create on "/tmp/test/a"
2023/01/18 10:39:12.589236 [D] dispatching notify.Remove on "/tmp/test/a"
2023/01/18 10:39:12.589256 [D] dispatching notify.Remove on "/tmp/test/a"
(*notify.event)(0xc00019e0f0)(notify.Remove: "/tmp/test/a")
(*notify.event)(0xc00019e090)(notify.Remove: "/tmp/test/a")

on:

Linux cork 6.1.6-arch1-3 #1 SMP PREEMPT_DYNAMIC Mon, 16 Jan 2023 12:51:23 +0000 x86_64 GNU/Linux

Seams to only happen for folder removal though both rm -Rf and rmdir is affected.

commented

OK so inotify gets a rouge 0x40000000 value, not sure what it means. It isn't listed in the man page...:

package main

import (
        "github.com/davecgh/go-spew/spew"
        "github.com/rjeczalik/notify"
)

func main() {
        events := make(chan notify.EventInfo, 10)
        if err := notify.Watch("/tmp/test/...", events, notify.Remove, notify.Rename); err != nil {
                panic(err.Error())
        }

        for event := range events {
                spew.Dump(event)
                spew.Dump(event.Sys())
        }
}

actions:

/tmp/test$ mkdir a
/tmp/test$ mv a b
/tmp/test$ rmdir b

log:

(*notify.event)(0xc0001ca060)(notify.Rename: "/tmp/test/a")
(*unix.InotifyEvent)(0xc0001ca060)({
 Wd: (int32) 2,
 Mask: (uint32) 2048,
 Cookie: (uint32) 0,
 Len: (uint32) 0
})
(*notify.event)(0xc0001ca000)(notify.Rename: "/tmp/test/a")
(*unix.InotifyEvent)(0xc0001ca000)({
 Wd: (int32) 1,
 Mask: (uint32) 1073741888,
 Cookie: (uint32) 7450,
 Len: (uint32) 0
})
(*notify.event)(0xc0001ca0f0)(notify.Remove: "/tmp/test/b")
(*unix.InotifyEvent)(0xc0001ca0f0)({
 Wd: (int32) 1,
 Mask: (uint32) 1073742336,
 Cookie: (uint32) 0,
 Len: (uint32) 0
})
(*notify.event)(0xc0001ca090)(notify.Remove: "/tmp/test/b")
(*unix.InotifyEvent)(0xc0001ca090)({
 Wd: (int32) 2,
 Mask: (uint32) 1024,
 Cookie: (uint32) 0,
 Len: (uint32) 0
})
commented
	name := event.Event().String()
	mask := event.Sys().(*unix.InotifyEvent).Mask
	if name == "notify.Rename" && (mask&unix.IN_MOVE_SELF) != 0 {
		continue
	} else if name == "notify.Remove" && (mask&unix.IN_DELETE_SELF) != 0 {
		continue
	}

Seams to give the correct effect. Not a fix though.