Skip to content

Commit d272faa

Browse files
MoLowtargos
authored andcommitted
fs: fix nonNativeWatcher leak of StatWatchers
PR-URL: #45501 Reviewed-By: Yagiz Nizipli <[email protected]>
1 parent 1784768 commit d272faa

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

lib/internal/fs/recursive_watch.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,11 @@ class FSWatcher extends EventEmitter {
154154
this.#symbolicFiles.add(f);
155155
}
156156

157+
this.#files.set(f, file);
157158
if (file.isFile()) {
158159
this.#watchFile(f);
159-
} else {
160-
this.#files.set(f, file);
161-
162-
if (file.isDirectory() && !file.isSymbolicLink()) {
163-
await this.#watchFolder(f);
164-
}
160+
} else if (file.isDirectory() && !file.isSymbolicLink()) {
161+
await this.#watchFolder(f);
165162
}
166163
}
167164
}

test/parallel/test-fs-watch-recursive.js

+27
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,33 @@ tmpdir.refresh();
213213
});
214214
})().then(common.mustCall());
215215

216+
217+
(async () => {
218+
// Assert recursive watch does not leak handles
219+
const rootDirectory = fs.mkdtempSync(testDir + path.sep);
220+
const testDirectory = path.join(rootDirectory, 'test-7');
221+
const filePath = path.join(testDirectory, 'only-file.txt');
222+
fs.mkdirSync(testDirectory);
223+
224+
let watcherClosed = false;
225+
const watcher = fs.watch(testDirectory, { recursive: true });
226+
watcher.on('change', common.mustCallAtLeast(async (event, filename) => {
227+
await setTimeout(common.platformTimeout(100));
228+
if (filename === path.basename(filePath)) {
229+
watcher.close();
230+
watcherClosed = true;
231+
}
232+
await setTimeout(common.platformTimeout(100));
233+
assert(!process._getActiveHandles().some((handle) => handle.constructor.name === 'StatWatcher'));
234+
}));
235+
236+
process.on('exit', function() {
237+
assert(watcherClosed, 'watcher Object was not closed');
238+
});
239+
await setTimeout(common.platformTimeout(100));
240+
fs.writeFileSync(filePath, 'content');
241+
})().then(common.mustCall());
242+
216243
(async () => {
217244
// Handle non-boolean values for options.recursive
218245

0 commit comments

Comments
 (0)