Skip to content

Commit 568377f

Browse files
mcollinatargos
authored andcommitted
fs: do not crash if the watched file is removed while setting up watch
Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: #53452 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
1 parent 9f32002 commit 568377f

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

lib/internal/fs/recursive_watch.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class FSWatcher extends EventEmitter {
8383
this.#closed = true;
8484

8585
for (const file of this.#files.keys()) {
86-
this.#watchers.get(file).close();
86+
this.#watchers.get(file)?.close();
8787
this.#watchers.delete(file);
8888
}
8989

@@ -98,7 +98,7 @@ class FSWatcher extends EventEmitter {
9898
for (const filename of this.#files.keys()) {
9999
if (StringPrototypeStartsWith(filename, file)) {
100100
this.#files.delete(filename);
101-
this.#watchers.get(filename).close();
101+
this.#watchers.get(filename)?.close();
102102
this.#watchers.delete(filename);
103103
}
104104
}
@@ -126,9 +126,16 @@ class FSWatcher extends EventEmitter {
126126
this.#symbolicFiles.add(f);
127127
}
128128

129-
this.#watchFile(f);
130-
if (file.isDirectory() && !file.isSymbolicLink()) {
131-
this.#watchFolder(f);
129+
try {
130+
this.#watchFile(f);
131+
if (file.isDirectory() && !file.isSymbolicLink()) {
132+
this.#watchFolder(f);
133+
}
134+
} catch (err) {
135+
// Ignore ENOENT
136+
if (err.code !== 'ENOENT') {
137+
throw err;
138+
}
132139
}
133140
}
134141
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
if (!common.isLinux)
6+
common.skip('This test can run only on Linux');
7+
8+
// Test that the watcher do not crash if the file "disappears" while
9+
// watch is being set up.
10+
11+
const path = require('node:path');
12+
const fs = require('node:fs');
13+
const { spawn } = require('node:child_process');
14+
15+
const tmpdir = require('../common/tmpdir');
16+
const testDir = tmpdir.path;
17+
tmpdir.refresh();
18+
19+
const watcher = fs.watch(testDir, { recursive: true });
20+
watcher.on('change', function(event, filename) {
21+
// This console.log makes the error happen
22+
// do not remove
23+
console.log(filename, event);
24+
});
25+
26+
const testFile = path.join(testDir, 'a');
27+
const child = spawn(process.argv[0], ['-e', `const fs = require('node:fs'); for (let i = 0; i < 10000; i++) { const fd = fs.openSync('${testFile}', 'w'); fs.writeSync(fd, Buffer.from('hello')); fs.rmSync('${testFile}') }`], {
28+
stdio: 'inherit'
29+
});
30+
31+
child.on('exit', function() {
32+
watcher.close();
33+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy