]> go.fuhry.dev Git - fsnotify.git/commitdiff
Fixed symlink notifications on Linux
authorTudor Golubenco <tudor.g@gmail.com>
Thu, 9 May 2013 16:55:29 +0000 (16:55 +0000)
committerTudor Golubenco <tudor.g@gmail.com>
Thu, 9 May 2013 16:55:29 +0000 (16:55 +0000)
The linux code used to ignore events on the files that os.Stat reports as
non existing. This ignores the CREATEion of broken links, but monitoring
those can be useful, for example /proc/<pid>/fd/ contains fake links
for all sockets.

The patch simply replaces os.Stat with os.Lstat to solve the issue.

I updated the fsnotify_symlink_test.go to what I consider the correct
behavior but unfortunately couldn't test under windows, so I'm not sure
if it breaks the test there or not.

fsnotify_linux.go
fsnotify_symlink_test.go

index 074ff6028cac04664e9b41835df74fbeb1b1bb81..898084158c400cb462cec7fad12b6bc6c8a0f537 100644 (file)
@@ -249,7 +249,7 @@ func (e *FileEvent) ignoreLinux() bool {
                e.mask&IN_DELETE_SELF == IN_DELETE_SELF ||
                e.mask&IN_MOVED_FROM == IN_MOVED_FROM ||
                e.mask&IN_MOVE_SELF == IN_MOVE_SELF) {
-               if _, statErr := os.Stat(e.Name); os.IsNotExist(statErr) {
+               if _, statErr := os.Lstat(e.Name); os.IsNotExist(statErr) {
                        return true
                }
        }
index 44e1653a021f6779ae604dc463129320f8693692..fdf6f452ce8d4c293f128a98c3855bbe12d82940 100644 (file)
@@ -9,6 +9,7 @@ package fsnotify
 import (
        "os"
        "testing"
+       "time"
 )
 
 func TestFsnotifyFakeSymlink(t *testing.T) {
@@ -26,11 +27,6 @@ func TestFsnotifyFakeSymlink(t *testing.T) {
        }
        defer os.RemoveAll(testDir)
 
-       if os.Symlink("_test/zzz", "_test/zzznew") != nil {
-               t.Fatalf("Failed to create bogus symlink: %s", err)
-       }
-       t.Logf("Created bogus symlink")
-
        var errorsReceived = 0
        // Receive errors on the error channel on a separate goroutine
        go func() {
@@ -40,16 +36,49 @@ func TestFsnotifyFakeSymlink(t *testing.T) {
                }
        }()
 
+       // Count the CREATE events received
+       var createEventsReceived = 0
+       var otherEventsReceived = 0
+       go func() {
+               for ev := range watcher.Event {
+                       t.Logf("Received error: %s", ev)
+                       if ev.IsCreate() {
+                               createEventsReceived++
+                       } else {
+                               otherEventsReceived++
+                       }
+               }
+       }()
+
        // Add a watch for testDir
        err = watcher.Watch(testDir)
        if err != nil {
                t.Fatalf("Watcher.Watch() failed: %s", err)
        }
 
+       if os.Symlink("_test/zzz", "_test/zzznew") != nil {
+               t.Fatalf("Failed to create bogus symlink: %s", err)
+       }
+       t.Logf("Created bogus symlink")
+
+       // We expect this event to be received almost immediately, but let's wait 500 ms to be sure
+       time.Sleep(500 * time.Millisecond)
+
        // Should not be error, just no events for broken links (watching nothing)
        if errorsReceived > 0 {
                t.Fatal("fsnotify errors have been received.")
        }
+       if otherEventsReceived > 0 {
+               t.Fatal("fsnotify other events received on the broken link")
+       }
+
+       // Except for 1 create event (for the link itself)
+       if createEventsReceived == 0 {
+               t.Fatal("fsnotify create events were not received after 500 ms")
+       }
+       if createEventsReceived > 1 {
+               t.Fatal("fsnotify more create events received than expected")
+       }
 
        // Try closing the fsnotify instance
        t.Log("calling Close()")