From 671de6224cc0e92eecc9bc77068d7e6ee53d14f5 Mon Sep 17 00:00:00 2001 From: Tudor Golubenco Date: Thu, 9 May 2013 16:55:29 +0000 Subject: [PATCH] Fixed symlink notifications on Linux 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//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 | 2 +- fsnotify_symlink_test.go | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/fsnotify_linux.go b/fsnotify_linux.go index 074ff60..8980841 100644 --- a/fsnotify_linux.go +++ b/fsnotify_linux.go @@ -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 } } diff --git a/fsnotify_symlink_test.go b/fsnotify_symlink_test.go index 44e1653..fdf6f45 100644 --- a/fsnotify_symlink_test.go +++ b/fsnotify_symlink_test.go @@ -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()") -- 2.50.1