Skip to content

Commit a7e03d3

Browse files
mcollinaaduh95
authored andcommitted
fs: fixes recursive fs.watch crash on Linux when deleting files
Signed-off-by: Matteo Collina <hello@matteocollina.com> Fixes: #52018 PR-URL: #52349 Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent ed080d8 commit a7e03d3

2 files changed

Lines changed: 38 additions & 3 deletions

File tree

‎lib/internal/fs/recursive_watch.js‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,16 @@ class FSWatcher extends EventEmitter {
157157
persistent: this.#options.persistent,
158158
},(eventType,filename)=>{
159159
constexistingStat=this.#files.get(file);
160-
constcurrentStats=statSync(file);
160+
letcurrentStats;
161161

162-
this.#files.set(file,currentStats);
162+
try{
163+
currentStats=statSync(file);
164+
this.#files.set(file,currentStats);
165+
}catch{
166+
// This happens if the file was removed
167+
}
163168

164-
if(currentStats.birthtimeMs===0&&existingStat.birthtimeMs!==0){
169+
if(currentStats===undefined||(currentStats.birthtimeMs===0&&existingStat.birthtimeMs!==0)){
165170
// The file is now deleted
166171
this.#files.delete(file);
167172
this.#watchers.delete(file);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
consttmpdir=require('../common/tmpdir');
5+
constfs=require('fs');
6+
7+
if(common.isSunOS)
8+
common.skip('SunOS behaves differently');
9+
10+
tmpdir.refresh();
11+
12+
fs.mkdirSync(tmpdir.resolve('./parent/child'),{recursive: true});
13+
14+
fs.writeFileSync(tmpdir.resolve('./parent/child/test.tmp'),'test');
15+
16+
consttoWatch=tmpdir.resolve('./parent');
17+
18+
constonFileUpdate=common.mustCallAtLeast((eventType,filename)=>{
19+
// We are only checking for the filename to avoid having Windows, Linux and Mac specific assertions
20+
if(fs.readdirSync(tmpdir.resolve('./parent')).length===0){
21+
watcher.close();
22+
}
23+
},1);
24+
25+
constwatcher=fs.watch(toWatch,{recursive: true},onFileUpdate);
26+
27+
// We must wait a bit `fs.rm()` to let the watcher be set up properly
28+
setTimeout(()=>{
29+
fs.rm(tmpdir.resolve('./parent/child'),{recursive: true},common.mustCall());
30+
},common.platformTimeout(500));

0 commit comments

Comments
 (0)