- Copy
main.go
above - create directory with a bunch of files:
mkdir files for i in {1..4095}; do touch files/$i; done
- Confirm that you can successfully watch this many files:
go run main.go $(find ./files)
- See log message "Watching 4096 paths"
- Change a file (e.g.
touch files/123
) and see the Go util report the change
- Add another file:
touch files/one-too-many
- Observe that filewatching is now broken??
go run main.go $(find ./files)
- See log message "Watching 4097 paths"
- Change a file (e.g.
touch files/456
); this change is NOT reported by the Go util
Last active
June 12, 2020 18:24
-
-
Save maiamcc/c355a459d81b7903b034b443d00c5a17 to your computer and use it in GitHub Desktop.
fsevents can't watch more than 4096 files (repro)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"os" | |
"os/signal" | |
"syscall" | |
"time" | |
"github.com/tilt-dev/fsevents" | |
) | |
func main() { | |
args := os.Args[1:] | |
if len(args) == 0 { | |
log.Fatal("Pass at least one filepath to watch") | |
} | |
stop := make(chan bool) | |
watchForExit(stop) | |
stream := newStream(args) | |
log.Printf("Watching %d paths", len(stream.Paths)) | |
stream.Start() | |
for { | |
select { | |
case <-stop: | |
stream.Stop() | |
return | |
case events, ok := <-stream.Events: | |
if !ok { | |
return | |
} | |
for _, e := range events { | |
log.Printf("- %s", e.Path) | |
} | |
} | |
} | |
} | |
func newStream(paths []string) *fsevents.EventStream { | |
stream := &fsevents.EventStream{ | |
Latency: 1 * time.Millisecond, | |
Flags: fsevents.FileEvents, | |
EventID: fsevents.LatestEventID(), | |
} | |
for _, p := range paths { | |
stream.Paths = append(stream.Paths, p) | |
} | |
return stream | |
} | |
func watchForExit(stopChan chan bool) { | |
sigs := make(chan os.Signal, 1) | |
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | |
go func() { | |
<-sigs | |
stopChan <- true // send stop signal | |
// If we get another SIGINT/SIGTERM, OR it takes too long to exit | |
// after sending signal, just quit | |
select { | |
case <-sigs: | |
log.Println("force quitting...") | |
os.Exit(1) | |
case <-time.After(2 * time.Second): | |
log.Println("Stop signal sent but app still running; forcibly exiting.") | |
os.Exit(1) | |
} | |
}() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment