Skip to content

Commit 7fa97d4

Browse files
TimothyGurvagg
authored andcommitted
src: make FSEventWrap/StatWatcher::Start more robust
PR-URL: #17432 Fixes: #17430 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 8292bc3 commit 7fa97d4

File tree

4 files changed

+35
-23
lines changed

4 files changed

+35
-23
lines changed

src/fs_event_wrap.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
112112

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

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

src/node_stat_watcher.cc

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

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

test/parallel/test-fs-watch.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ for (const testCase of cases) {
6565
assert.strictEqual(eventType, 'change');
6666
assert.strictEqual(argFilename, testCase.fileName);
6767

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

test/parallel/test-fs-watchfile.js

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,27 +44,30 @@ tmpdir.refresh();
4444
// time, the callback should be invoked again with proper values in stat object
4545
let fileExists = false;
4646

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

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

0 commit comments

Comments
 (0)