Skip to content

Commit

Permalink
Merge branch 'main' into refactor-integrated-test
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo82148 committed Mar 6, 2024
2 parents 158fee3 + e3276b6 commit dbdbadc
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 0 deletions.
3 changes: 3 additions & 0 deletions inotify.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,15 @@ func (w *Watcher) isClosed() bool {

// Close removes all watches and closes the events channel.
func (w *Watcher) Close() error {
w.mu.Lock()
if w.isClosed() {
w.mu.Unlock()
return nil
}

// Send 'close' signal to goroutine, and set the Watcher to closed.
close(w.done)
w.mu.Unlock()

// Causes any blocking reads to return with an error, provided the file still supports deadline operations
err := w.inotifyFile.Close()
Expand Down
15 changes: 15 additions & 0 deletions integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,18 @@ func TestRemove(t *testing.T) {
}
})
}

// Make sure Close() doesn't race; hard to write a good reproducible test for
// this, but running it 150 times seems to reproduce it in ~75% of cases and
// isn't too slow (~0.06s on my system).
func TestCloseRace(t *testing.T) {
for i := 0; i < 150; i++ {
w, err := NewWatcher()
if err != nil {
t.Fatal(err)
}
go w.Close()
go w.Close()
go w.Close()
}
}
6 changes: 6 additions & 0 deletions windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ func NewWatcher() (*Watcher, error) {

// Close removes all watches and closes the events channel.
func (w *Watcher) Close() error {
w.mu.Lock()
if w.isClosed {
w.mu.Unlock()
return nil
}
w.isClosed = true
w.mu.Unlock()

// Send "quit" message to the reader goroutine
ch := make(chan error)
Expand All @@ -67,9 +70,12 @@ func (w *Watcher) Close() error {

// Add starts watching the named file or directory (non-recursively).
func (w *Watcher) Add(name string) error {
w.mu.Lock()
if w.isClosed {
w.mu.Unlock()
return errors.New("watcher already closed")
}
w.mu.Unlock()
in := &input{
op: opAddWatch,
path: filepath.Clean(name),
Expand Down

0 comments on commit dbdbadc

Please sign in to comment.