Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing Remove Event when file handle open before for Linux #194

Closed
lbgogo88 opened this issue Jan 22, 2017 · 4 comments · Fixed by #260
Closed

Missing Remove Event when file handle open before for Linux #194

lbgogo88 opened this issue Jan 22, 2017 · 4 comments · Fixed by #260
Labels

Comments

@lbgogo88
Copy link

lbgogo88 commented Jan 22, 2017

Before reporting an issue, please ensure you are using the latest release of fsnotify.

Which operating system (GOOS) and version are you using?

Linux: lsb_release -a
macOS: sw_vers
Windows: systeminfo | findstr /B /C:OS

Linux:
LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch
Distributor ID: CentOS
Description: CentOS release 5.8 (Final)
Release: 5.8
Codename: Final

Please describe the issue that occurred.

Missing Remove Event when got file handle already open before. See the sample.

And I review the fsnotify code(fsnotify/inotify.go/func newEvent) found that unix.IN_ATTRIB was catched then e.Op was set to Chmod when rm -f $filename;echo >$filename done.

After that the event was ignored by "func ignoreLinux"

For this reason, I must watch the directory to walk around.

Are you able to reproduce the issue? Please provide steps to reproduce and a code sample if possible.


package main

import (
        "github.com/fsnotify/fsnotify"
        "os"
        "fmt"
)

func main() {
        var err error
        path := os.Args[1]
        watcher,_ := fsnotify.NewWatcher()

        watcher.Add(path)
        done := make(chan bool)

        os.Open(path)
        go func(){
                var ev fsnotify.Event
                for {
                        select {
                        case ev = <-watcher.Events:
                        case err = <-watcher.Errors:
                                fmt.Println("##ERR",err)
                        }
                        fmt.Println(ev)
                }
        }()

        <-done
}
@vladlosev
Copy link

What is happening here is that Linux's inotify actually delivers two notifications when a file is deleted. It first sends IN_ATTRIB to indicate that the number of file links have been decremented, and follows up by IN_DELETE_SELF to indicate that the file is deleted from disk. When some process is has open handles to the file, the file is not actually deleted from disk until all open handles are closed, and thus the second notification is also delayed. But fsnotify propagates only the second notification and drops the first one after statting the file name and seeing it gone.

Here is a go test for this.

func TestInotifyDeleteOpenFile(t *testing.T) {
	testDir := tempMkdir(t)
	defer os.RemoveAll(testDir)

	testFile := filepath.Join(testDir, "testfile")

	handle, err := os.Create(testFile)
	if err != nil {
		t.Fatalf("Create failed: %v", err)
	}

	w, err := NewWatcher()
	if err != nil {
		t.Fatalf("Failed to create watcher: %v", err)
	}
	defer w.Close()

	err = w.Add(testFile)
	if err != nil {
		t.Fatalf("Failed to add watch for %s: %v", testFile, err)
	}

	err = os.Remove(testFile)
	if err != nil {
		t.Fatalf("Failed to remove %s: %v", testFile, err)
	}

	var event Event

	func() {
		defer handle.Close()

		select {
		case event = <-w.Events:
		case <-time.After(100 * time.Millisecond):
			t.Fatalf("Expected event not delivered")
		}
	}()

	if event.Op != Remove {
		t.Fatalf("Expected event type %s, got: %v", Remove, event.Op)
	}

	w.Close()

	// Wait for the close to complete.
	time.Sleep(50 * time.Millisecond)
	isWatcherReallyClosed(t, w)
}

I can see a few options for dealing with this, none of them perfect:

  1. Convert the IN_ATTRIB notification into Remove for files which do not show up on disk. This will cause fsnotify to always deliver two Remove notifications. That may break some existing clients.
  2. Deliver the Chmod notification even for files that do not appear on disk anymore. This will allow clients at least some notification about what's happening with the file. This will probably also affect some clients but I believe fewer are checking Chmod events than Delete ones.
  3. Introduce a special watching mode that will treat open files correctly. This will require addition to the API.

@tiwaana
Copy link

tiwaana commented Mar 20, 2017

since its a library, I will prefer both event should be delivered to clients. This will keep policies out of this layer.

@rvadim
Copy link

rvadim commented Apr 18, 2017

Im creating log forwarder and try to using fsnotify. Workaround this by getting stat every iteration =(

@nathany
Copy link
Contributor

nathany commented Oct 5, 2019

Thanks for the report. #260 should resolve this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants