Skip to content

Commit d879b63

Browse files
TimothyGuMylesBorins
authored andcommitted
src: make FSEventWrap/StatWatcher::Start more robust
PR-URL: #17432 Fixes: #17430 Reviewed-By: James M Snell <[email protected]>
1 parent 977fb13 commit d879b63

File tree

4 files changed

+35
-23
lines changed

4 files changed

+35
-23
lines changed

src/fs_event_wrap.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
111111

112112
FSEventWrap* wrap;
113113
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
114-
CHECK_EQ(wrap->initialized_, false);
114+
if (wrap->initialized_)
115+
return args.GetReturnValue().Set(0);
115116

116117
static const char kErrMsg[] = "filename must be a string or Buffer";
117118
if (args.Length() < 1)

src/node_stat_watcher.cc

+7-1
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,15 @@ void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) {
111111
const bool persistent = args[1]->BooleanValue();
112112
const uint32_t interval = args[2]->Uint32Value();
113113

114-
if (!persistent)
114+
if (uv_is_active(reinterpret_cast<uv_handle_t*>(wrap->watcher_)))
115+
return;
116+
// Safe, uv_ref/uv_unref are idempotent.
117+
if (persistent)
118+
uv_ref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
119+
else
115120
uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
116121
uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
122+
117123
wrap->ClearWeak();
118124
}
119125

test/parallel/test-fs-watch.js

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ for (const testCase of cases) {
6464
assert.strictEqual(eventType, 'change');
6565
assert.strictEqual(argFilename, testCase.fileName);
6666

67+
watcher.start(); // should not crash
68+
6769
// end of test case
6870
watcher.close();
6971
}));

test/parallel/test-fs-watchfile.js

+24-21
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,30 @@ common.refreshTmpDir();
5252
// time, the callback should be invoked again with proper values in stat object
5353
let fileExists = false;
5454

55-
fs.watchFile(enoentFile, { interval: 0 }, common.mustCall(function(curr, prev) {
56-
if (!fileExists) {
57-
// If the file does not exist, all the fields should be zero and the date
58-
// fields should be UNIX EPOCH time
59-
assert.deepStrictEqual(curr, expectedStatObject);
60-
assert.deepStrictEqual(prev, expectedStatObject);
61-
// Create the file now, so that the callback will be called back once the
62-
// event loop notices it.
63-
fs.closeSync(fs.openSync(enoentFile, 'w'));
64-
fileExists = true;
65-
} else {
66-
// If the ino (inode) value is greater than zero, it means that the file is
67-
// present in the filesystem and it has a valid inode number.
68-
assert(curr.ino > 0);
69-
// As the file just got created, previous ino value should be lesser than
70-
// or equal to zero (non-existent file).
71-
assert(prev.ino <= 0);
72-
// Stop watching the file
73-
fs.unwatchFile(enoentFile);
74-
}
75-
}, 2));
55+
const watcher =
56+
fs.watchFile(enoentFile, { interval: 0 }, common.mustCall((curr, prev) => {
57+
if (!fileExists) {
58+
// If the file does not exist, all the fields should be zero and the date
59+
// fields should be UNIX EPOCH time
60+
assert.deepStrictEqual(curr, expectedStatObject);
61+
assert.deepStrictEqual(prev, expectedStatObject);
62+
// Create the file now, so that the callback will be called back once the
63+
// event loop notices it.
64+
fs.closeSync(fs.openSync(enoentFile, 'w'));
65+
fileExists = true;
66+
} else {
67+
// If the ino (inode) value is greater than zero, it means that the file
68+
// is present in the filesystem and it has a valid inode number.
69+
assert(curr.ino > 0);
70+
// As the file just got created, previous ino value should be lesser than
71+
// or equal to zero (non-existent file).
72+
assert(prev.ino <= 0);
73+
// Stop watching the file
74+
fs.unwatchFile(enoentFile);
75+
}
76+
}, 2));
77+
78+
watcher.start(); // should not crash
7679

7780
// Watch events should callback with a filename on supported systems.
7881
// Omitting AIX. It works but not reliably.

0 commit comments

Comments
 (0)