Skip to content

Commit

Permalink
fix: prevent recursive unwatch if watchpoints left
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianKramm committed Jul 19, 2021
1 parent 2a8f495 commit de179dd
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
50 changes: 50 additions & 0 deletions notify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,56 @@ func TestRenameInRoot(t *testing.T) {
}
}

func mustWatch(t *testing.T, path string) chan EventInfo {
c := make(chan EventInfo, 1)
err := Watch(path+"...", c, All)
if err != nil {
t.Fatal(err)
}

return c
}

func TestStopChild(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notify_test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)

// create test dir
err = os.MkdirAll(filepath.Join(tmpDir, "a/b/c"), 0755)
if err != nil {
t.Fatal(err)
}

// watch a child and parent path across multiple channels.
// this can happen in any order.
ch1 := mustWatch(t, filepath.Join(tmpDir, "a"))
ch2 := mustWatch(t, filepath.Join(tmpDir, "a/b/c"))

// this leads to tmpDir/a being unwatched
Stop(ch2)

// fire an event that will never show up because the watchpoint for ./a is removed
// as well.
filePath := filepath.Join(tmpDir, "a/b/c/d")
go func() { _ = ioutil.WriteFile(filePath, []byte("X"), 0664) }()

timeout := time.After(5 * time.Second)
for {
select {
case ev := <-ch1:
t.Log(filePath, ev.Path(), ev.Event())
if ev.Path() == filePath && ev.Event() == Write {
return
}
case <-timeout:
t.Fatal("timed out before receiving event")
}
}
}

func TestRecreated(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notify_test-")
if err != nil {
Expand Down
13 changes: 8 additions & 5 deletions tree_recursive.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ func (t *recursiveTree) Watch(path string, c chan<- EventInfo, events ...Event)
func (t *recursiveTree) Stop(c chan<- EventInfo) {
var err error
fn := func(nd node) (e error) {
isRecursive := watchIsRecursive(nd)
diff := watchDel(nd, c, all)
switch {
case diff == none && watchTotal(nd) == 0:
Expand All @@ -315,13 +316,15 @@ func (t *recursiveTree) Stop(c chan<- EventInfo) {
case diff == none:
// Removing c from nd does not require shrinking its eventset.
case diff[1] == 0:
if watchIsRecursive(nd) {
e = t.w.RecursiveUnwatch(nd.Name)
} else {
e = t.w.Unwatch(nd.Name)
if watchTotal(nd) == 0 {
if isRecursive {
e = t.w.RecursiveUnwatch(nd.Name)
} else {
e = t.w.Unwatch(nd.Name)
}
}
default:
if watchIsRecursive(nd) {
if isRecursive {
e = t.w.RecursiveRewatch(nd.Name, nd.Name, diff[0], diff[1])
} else {
e = t.w.Rewatch(nd.Name, diff[0], diff[1])
Expand Down

0 comments on commit de179dd

Please sign in to comment.