Skip to content

Commit

Permalink
inotify: don't ignore events for files that don't exist (#470)
Browse files Browse the repository at this point in the history
This is quite an odd check, leading to an inconsistent event stream,
which also doesn't match what other platforms do. If you do a "CREATE +
MODIFY + REMOVE" in quick succession then you probably *want* all three
events. If you don't want to operate on non-existing files, then you can
check this in your application code.

You need to do that already, since this check is far from reliable. In
the time between this check and the application code doing something
with an event the file may have been deleted already.

I looked a bit at the history of this, and looks like it was added in
2013 with cc2c34e; issue 36 refers to this issue on the old repo, which
mentions it fixes a memory leak: howeyc/fsnotify#36

I can't reproduce that at all; using the CLI from #463 modified to print
the memory and running:

	for i in $(seq 0 10000); { touch $i; rm $i }

Memory stays at about 100/110K in both the current main branch and this.

So I think it should be safe to remove.
  • Loading branch information
arp242 committed Jul 29, 2022
1 parent f0aceb2 commit 1a7b6ef
Showing 1 changed file with 1 addition and 22 deletions.
23 changes: 1 addition & 22 deletions inotify.go
Expand Up @@ -279,7 +279,7 @@ func (w *Watcher) readEvents() {
event := newEvent(name, mask)

// Send the events that are not ignored on the events channel
if !event.ignoreLinux(mask) {
if mask&unix.IN_IGNORED == 0 {
select {
case w.Events <- event:
case <-w.done:
Expand All @@ -293,27 +293,6 @@ func (w *Watcher) readEvents() {
}
}

// Certain types of events can be "ignored" and not sent over the Events
// channel. Such as events marked ignore by the kernel, or MODIFY events
// against files that do not exist.
func (e *Event) ignoreLinux(mask uint32) bool {
// Ignore anything the inotify API says to ignore
if mask&unix.IN_IGNORED == unix.IN_IGNORED {
return true
}

// If the event is Create or Write, the file must exist, or the
// event will be suppressed.
// *Note*: this was put in place because it was seen that a Write
// event was sent after the Remove. This ignores the Write and
// assumes a Remove will come or has come if the file doesn't exist.
if e.Op&Create == Create || e.Op&Write == Write {
_, statErr := os.Lstat(e.Name)
return os.IsNotExist(statErr)
}
return false
}

// newEvent returns an platform-independent Event based on an inotify mask.
func newEvent(name string, mask uint32) Event {
e := Event{Name: name}
Expand Down

0 comments on commit 1a7b6ef

Please sign in to comment.