paulmillr / chokidar

Minimal and efficient cross-platform file watching library
https://paulmillr.com
MIT License
11.04k stars 586 forks source link

EBADF error when watching tons of files on macos #1385

Open bluwy opened 3 weeks ago

bluwy commented 3 weeks ago

Describe the bug

When watching many files on macos. spawning a child process causes EBADF errors consistently. (likely due to reaching maximum file descriptors?)

Versions (please complete the following information):

To Reproduce:

https://github.com/bluwy/chokidar-lots-of-files-repro

Steps:

  1. node gen.js (generate files in src/ to watch)
  2. node test.js (watches files and tries to run the ls bash command)

Expected behavior

EBADF errors should not appear when spawning a child process after watching tons of files.

Additional context

With chokidar v4 removing fsevents and using fs.watch, this issue is blocking Vite and Nuxt from upgrading to v4 as there's no easy workaround to the problem (other than usePolling).

Users have also tried adjusting ulimit to extend the maximum file descriptors, but it didn't fix the issue.

paulmillr commented 2 weeks ago

fs.watch with {recursive: true} can be used as backend. That would be breaking change (v5), because it is not available on Linux / IBM until node.js v20. It also comes with following caveats:

It's unclear how to solve issue number one.

bluwy commented 2 weeks ago

Re no1, I suppose the only way it to test against EPERM errors and stat the filesystem again for the new change, but you won't be able to find out the new name if it's moved I think.

Re no2, yeah that's a huge bummer to workaround of. I'm not sure why there's no similar option yet, FWIW @parcel/watcher supports that (as a fs.watch replacement itself) but I suppose that's out of scope.

About Linux / IBM recursive support, I noticed that node manually implemented it on the JS side rather than natively (source 1, source 2), so perhaps there's not much gain using recursive there and what chokidar implements now should be on par perf-wise.

paulmillr commented 2 weeks ago

v4 moved over from our own native fsevents dep to reduce pain (of using native deps). Of course, we won't be using parcel.

Reverting to fsevents usage is a possibility if there's someone trustworthy willing to maintain it. Until then it's a no-go.

bluwy commented 2 weeks ago

That's fair. Another option is to figure out a workaround on macos, maybe there's a system/bash command that could fix this like linux.

43081j commented 2 weeks ago

Just to make sure I understood correctly: the current problem then is because we implement recursive watching ourselves? So with a huge amount of files, we watch each individual one

But if we could use node's recursive, it'd probably do the same under the hood and hit the descriptor limit?

Maybe we could do some smarts around watching parents or something.

Do we know any repos where this problem happens often? Would be good to see what kind of structure we're dealing with in real world

bluwy commented 2 weeks ago

Yes, but for recursive, it only does the same under the hood for linux (JS-based). Windows and macos have native recursive watching, which should be more efficient.

Unfortunately I haven't found any repros at the moment, but I'm planning to try to create one today.

bluwy commented 2 weeks ago

Here's a repro and I'm able to reproduce the issue too: https://github.com/bluwy/chokidar-lots-of-files-repro