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

2 files changed

Lines changed: 45 additions & 5 deletions

File tree

‎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(constfileofthis.#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(constfilenameofthis.#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+
throwerr;
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+
constcommon=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+
constpath=require('node:path');
12+
constfs=require('node:fs');
13+
const{ spawn }=require('node:child_process');
14+
15+
consttmpdir=require('../common/tmpdir');
16+
consttestDir=tmpdir.path;
17+
tmpdir.refresh();
18+
19+
constwatcher=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+
consttestFile=path.join(testDir,'a');
27+
constchild=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)