Skip to content

Commit

Permalink
fs: fix nonNativeWatcher leak of StatWatchers
Browse files Browse the repository at this point in the history
PR-URL: nodejs#45501
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
  • Loading branch information
MoLow committed Dec 31, 2022
1 parent 68cca1e commit 4b377e5
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
9 changes: 3 additions & 6 deletions lib/internal/fs/recursive_watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,11 @@ class FSWatcher extends EventEmitter {
this.#symbolicFiles.add(f);
}

this.#files.set(f, file);
if (file.isFile()) {
this.#watchFile(f);
} else {
this.#files.set(f, file);

if (file.isDirectory() && !file.isSymbolicLink()) {
await this.#watchFolder(f);
}
} else if (file.isDirectory() && !file.isSymbolicLink()) {
await this.#watchFolder(f);
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions test/parallel/test-fs-watch-recursive.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const common = require('../common');
const { setTimeout } = require('timers/promises');


const assert = require('assert');
Expand Down Expand Up @@ -52,3 +53,29 @@ if (common.isOSX) {
process.on('exit', function() {
assert(watcherClosed, 'watcher Object was not closed');
});

(async () => {
// Assert recursive watch does not leak handles
const rootDirectory = fs.mkdtempSync(testDir + path.sep);
const testDirectory = path.join(rootDirectory, 'test-7');
const filePath = path.join(testDirectory, 'only-file.txt');
fs.mkdirSync(testDirectory);

let watcherClosed = false;
const watcher = fs.watch(testDirectory, { recursive: true });
watcher.on('change', common.mustCallAtLeast(async (event, filename) => {
await setTimeout(common.platformTimeout(100));
if (filename === path.basename(filePath)) {
watcher.close();
watcherClosed = true;
}
await setTimeout(common.platformTimeout(100));
assert(!process._getActiveHandles().some((handle) => handle.constructor.name === 'StatWatcher'));
}));

process.on('exit', function() {
assert(watcherClosed, 'watcher Object was not closed');
});
await setTimeout(common.platformTimeout(100));
fs.writeFileSync(filePath, 'content');
})().then(common.mustCall());

0 comments on commit 4b377e5

Please sign in to comment.