Describe the bug
The Go race detector flags on concurrent read/write across goroutines when one is calling .Add() while the other calls .WatchList(). The issue was not present on v1.7.0 using the same test, but was introduced with v1.9.0 and persists on the main branch at v1.9.1-0.20250811202840-88b7b41337a8. I was unable to test on v1.8.0 as the same test just hangs.
==================
WARNING: DATA RACE
Read at 0x00c0001a40c0 by goroutine 10:
github.com/fsnotify/fsnotify.(*readDirChangesW).WatchList()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/backend_windows.go:178 +0x4ee
github.com/fsnotify/fsnotify.(*Watcher).WatchList()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/fsnotify.go:343 +0x4a
tst_test.TestWatchListRace.func1()
C:/Users/user/dev/tst/race_test.go:36 +0x33
Previous write at 0x00c0001a40c0 by goroutine 9:
github.com/fsnotify/fsnotify.(*readDirChangesW).addWatch()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/backend_windows.go:363 +0x814
github.com/fsnotify/fsnotify.(*readDirChangesW).readEvents()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/backend_windows.go:521 +0x655
github.com/fsnotify/fsnotify.newBackend.gowrap1()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/backend_windows.go:53 +0x33
Goroutine 10 (running) created at:
tst_test.TestWatchListRace()
C:/Users/user/dev/tst/race_test.go:30 +0x2f2
testing.tRunner()
C:/Program Files/Go/src/testing/testing.go:1934 +0x1c3
testing.(*T).Run.gowrap1()
C:/Program Files/Go/src/testing/testing.go:1997 +0x44
Goroutine 9 (running) created at:
github.com/fsnotify/fsnotify.newBackend()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/backend_windows.go:53 +0x32d
github.com/fsnotify/fsnotify.NewWatcher()
C:/Users/user/go/pkg/mod/github.com/fsnotify/fsnotify@v1.9.0/fsnotify.go:254 +0x64
tst_test.TestWatchListRace()
C:/Users/user/dev/tst/race_test.go:18 +0x56
testing.tRunner()
C:/Program Files/Go/src/testing/testing.go:1934 +0x1c3
testing.(*T).Run.gowrap1()
C:/Program Files/Go/src/testing/testing.go:1997 +0x44
==================
--- FAIL: TestWatchListRace (0.00s)
testing.go:1617: race detected during execution of test
FAIL
exit status 1
FAIL tst 0.327s
Code to Reproduce
go get github.com/fsnotify/fsnotify@main
//go:build windows
// +build windows
package fsnotify_race_test
import (
"os"
"path/filepath"
"testing"
"github.com/fsnotify/fsnotify"
)
// Reproduces: readDirChangesW.addWatch (write) vs WatchList (read).
func TestWatchListRace(t *testing.T) {
root := t.TempDir()
w, err := fsnotify.NewWatcher()
if err != nil {
t.Fatalf("NewWatcher: %v", err)
}
defer w.Close()
if err := w.Add(root); err != nil {
t.Fatalf("Add(root): %v", err)
}
// --- reader: continuously calls WatchList()
done := make(chan struct{})
go func() {
for {
select {
case <-done:
return
default:
_ = w.WatchList()
}
}
}()
// --- writer: Add() call => addWatch()
dir := filepath.Join(root, "test")
os.Mkdir(dir, 0o755)
_ = w.Add(dir)
close(done)
}
File operations to reproduce
N/A
Which operating system and version are you using?
OS Name: Microsoft Windows 11 Pro
OS Version: 10.0.26100 N/A Build 26100
OS Manufacturer: Microsoft Corporation
OS Configuration: Standalone Workstation
OS Build Type: Multiprocessor Free
Which fsnotify version are you using?
v1.9.0
Did you try the latest main branch?
Yes
Describe the bug
The Go race detector flags on concurrent read/write across goroutines when one is calling .Add() while the other calls .WatchList(). The issue was not present on v1.7.0 using the same test, but was introduced with v1.9.0 and persists on the main branch at v1.9.1-0.20250811202840-88b7b41337a8. I was unable to test on v1.8.0 as the same test just hangs.
Code to Reproduce
File operations to reproduce
N/A
Which operating system and version are you using?
OS Name: Microsoft Windows 11 Pro
OS Version: 10.0.26100 N/A Build 26100
OS Manufacturer: Microsoft Corporation
OS Configuration: Standalone Workstation
OS Build Type: Multiprocessor Free
Which fsnotify version are you using?
v1.9.0
Did you try the latest main branch?
Yes