chokidar: after closing, chokidar can still process events, can crash, can mess up jest
After calling .close(), some async events might still be in some “pipeline”. Handling those and emitting events is unexpected to the user, but can also lead to exceptions or even crashes of the node vm. (Events can be queued anywhere from await based function blocks, in nodejs, in the kernel.)
For us this was painful because we use jest for testing, it removes the require function after testing is done, but readdirp calls require() and can be invoked after close().
But worse, it seems interfacing with fsevents after close() can lead to assertions from the c-code, these two I’ve seen (but not investigated):
Assertion failed: (napi_call_function(env, recv, callback, 3, args, &recv) == napi_ok), function fse_dispatch_events, file ../src/fsevents.c, line 45.Assertion failed: (handle->flags & UV_HANDLE_CLOSING), function uv__finish_close, file ../deps/uv/src/unix/core.c, line 252.
Technically, chokidar should remove all its registered callbacks, abort all await based code blocks. Practically, a few early returns suffice. The below diff seems to solve all problems we had:
diff --git a/index.js b/index.js
index a79ba31..9ac49ac 100644
--- a/index.js
+++ b/index.js
@@ -501,6 +501,7 @@ emitWithAll(event, args) {
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
*/
async _emit(event, path, val1, val2, val3) {
+ if (this.closed) return;
const opts = this.options;
if (opts.cwd) path = sysPath.relative(opts.cwd, path);
/** @type Array<any> */
diff --git a/lib/fsevents-handler.js b/lib/fsevents-handler.js
index 7eba95c..c45ff70 100644
--- a/lib/fsevents-handler.js
+++ b/lib/fsevents-handler.js
@@ -221,6 +221,7 @@ async checkFd(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
}
handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) {
+ if (this.fsw.closed) return;
if (this.checkIgnored(path)) return;
if (event === 'unlink') {
@@ -329,6 +330,7 @@ _watchWithFsEvents(watchPath, realPath, transform, globFilter) {
* @returns {void}
*/
async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) {
+ if (this.fsw.closed) return;
// don't follow the same symlink more than once
if (this.fsw._symlinkPaths.has(fullPath)) return;
@@ -403,6 +405,7 @@ initWatch(realPath, path, wh, processPath) {
* @returns {void}
*/
async _addToFsEvents(path, transform, forceAdd, priorDepth) {
+ if (this.fsw.closed) return;
const opts = this.fsw.options;
const processPath = typeof transform === 'function' ? transform : (val => val);
@@ -411,6 +414,7 @@ async _addToFsEvents(path, transform, forceAdd, priorDepth) {
// evaluate what is at the path we're being asked to watch
try {
const stats = await statMethods[wh.statMethod](wh.watchPath);
+ if (this.fsw.closed) return;
if (this.fsw._isIgnored(wh.watchPath, stats)) {
throw null;
}
@@ -427,6 +431,7 @@ async _addToFsEvents(path, transform, forceAdd, priorDepth) {
directoryFilter: entry => wh.filterDir(entry),
...Option("depth", opts.depth - (priorDepth || 0))
}).on('data', (entry) => {
+ if (this.fsw.closed) return;
// need to check filterPath on dirs b/c filterDir is less restrictive
if (entry.stats.isDirectory() && !wh.filterPath(entry)) return;
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 16 (5 by maintainers)
Commits related to this issue
- Merge branch 'check-exit' - chokidar 3.00 and upwards hang on shutdown-->close. This is the last chokidar 2.x (2.1.6) release which does NOT exhibit that problem. ==> revert chokidar update to 3.x. Ve... — committed to GerHobbelt/live-server by GerHobbelt 5 years ago
- minimal change to FAIL chokidar i.e. hang live-server on shutdown: just update to chokidar 3.0.0. Very probably related to https://github.com/paulmillr/chokidar/issues/859 and https://github.com/paulm... — committed to GerHobbelt/live-server by GerHobbelt 5 years ago
- update all npm packages and chokidar to 3.1.1: still FAIL. Very probably related to https://github.com/paulmillr/chokidar/issues/859 and https://github.com/paulmillr/chokidar/issues/855. — committed to GerHobbelt/live-server by GerHobbelt 5 years ago
- Revert "minimal change to FAIL chokidar i.e. hang live-server on shutdown". Very probably related to https://github.com/paulmillr/chokidar/issues/859 and https://github.com/paulmillr/chokidar/issues/8... — committed to GerHobbelt/live-server by GerHobbelt 5 years ago
- enable running integration tests locally See https://github.com/paulmillr/chokidar/issues/855 for more details. — committed to cypress-io/cypress by andrew-codes 5 years ago
- allow list of search patterns in testFiles config option (#5402) * WIP: log spec search steps * add multiple files via glob test * allow testFiles to be a string or a list of strings to match ... — committed to cypress-io/cypress by bahmutov 5 years ago
This issue is still there on macOS 10.14.6!
I’m still seeing this issue in 3.0.2. Code was:
On OSX 10.14.5
I’ll push something out ASAP.
Pushed 3.0.1.
@paulmillr also seeing this with our VSCode tests that start and stop chokidar instances after switching to Chokidar 3:
I’ve spent two days and found another cause of the process crash. Try 3.2.4 in a few days, or github version right now.
Important change:
close()is now async, so you will need to doawait close()for correct work.cc @bpasero
Wondering what the plan is for releasing this fix? Hitting this issue and hope I can get my dev setup working again soon 😃