src: make FSEventWrap/StatWatcher::Start more robust
PR-URL: https://github.com/nodejs/node/pull/17432 Fixes: https://github.com/nodejs/node/issues/17430 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
11ebaff15c
commit
cd71fc1545
@ -111,7 +111,8 @@ void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
FSEventWrap* wrap;
|
FSEventWrap* wrap;
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
|
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
|
||||||
CHECK_EQ(wrap->initialized_, false);
|
if (wrap->initialized_)
|
||||||
|
return args.GetReturnValue().Set(0);
|
||||||
|
|
||||||
static const char kErrMsg[] = "filename must be a string or Buffer";
|
static const char kErrMsg[] = "filename must be a string or Buffer";
|
||||||
if (args.Length() < 1)
|
if (args.Length() < 1)
|
||||||
|
@ -111,9 +111,15 @@ void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) {
|
|||||||
const bool persistent = args[1]->BooleanValue();
|
const bool persistent = args[1]->BooleanValue();
|
||||||
const uint32_t interval = args[2]->Uint32Value();
|
const uint32_t interval = args[2]->Uint32Value();
|
||||||
|
|
||||||
if (!persistent)
|
if (uv_is_active(reinterpret_cast<uv_handle_t*>(wrap->watcher_)))
|
||||||
|
return;
|
||||||
|
// Safe, uv_ref/uv_unref are idempotent.
|
||||||
|
if (persistent)
|
||||||
|
uv_ref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
|
||||||
|
else
|
||||||
uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
|
uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
|
||||||
uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
|
uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
|
||||||
|
|
||||||
wrap->ClearWeak();
|
wrap->ClearWeak();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ for (const testCase of cases) {
|
|||||||
assert.strictEqual(eventType, 'change');
|
assert.strictEqual(eventType, 'change');
|
||||||
assert.strictEqual(argFilename, testCase.fileName);
|
assert.strictEqual(argFilename, testCase.fileName);
|
||||||
|
|
||||||
|
watcher.start(); // should not crash
|
||||||
|
|
||||||
// end of test case
|
// end of test case
|
||||||
watcher.close();
|
watcher.close();
|
||||||
}));
|
}));
|
||||||
|
@ -52,27 +52,30 @@ common.refreshTmpDir();
|
|||||||
// time, the callback should be invoked again with proper values in stat object
|
// time, the callback should be invoked again with proper values in stat object
|
||||||
let fileExists = false;
|
let fileExists = false;
|
||||||
|
|
||||||
fs.watchFile(enoentFile, { interval: 0 }, common.mustCall(function(curr, prev) {
|
const watcher =
|
||||||
if (!fileExists) {
|
fs.watchFile(enoentFile, { interval: 0 }, common.mustCall((curr, prev) => {
|
||||||
// If the file does not exist, all the fields should be zero and the date
|
if (!fileExists) {
|
||||||
// fields should be UNIX EPOCH time
|
// If the file does not exist, all the fields should be zero and the date
|
||||||
assert.deepStrictEqual(curr, expectedStatObject);
|
// fields should be UNIX EPOCH time
|
||||||
assert.deepStrictEqual(prev, expectedStatObject);
|
assert.deepStrictEqual(curr, expectedStatObject);
|
||||||
// Create the file now, so that the callback will be called back once the
|
assert.deepStrictEqual(prev, expectedStatObject);
|
||||||
// event loop notices it.
|
// Create the file now, so that the callback will be called back once the
|
||||||
fs.closeSync(fs.openSync(enoentFile, 'w'));
|
// event loop notices it.
|
||||||
fileExists = true;
|
fs.closeSync(fs.openSync(enoentFile, 'w'));
|
||||||
} else {
|
fileExists = true;
|
||||||
// If the ino (inode) value is greater than zero, it means that the file is
|
} else {
|
||||||
// present in the filesystem and it has a valid inode number.
|
// If the ino (inode) value is greater than zero, it means that the file
|
||||||
assert(curr.ino > 0);
|
// is present in the filesystem and it has a valid inode number.
|
||||||
// As the file just got created, previous ino value should be lesser than
|
assert(curr.ino > 0);
|
||||||
// or equal to zero (non-existent file).
|
// As the file just got created, previous ino value should be lesser than
|
||||||
assert(prev.ino <= 0);
|
// or equal to zero (non-existent file).
|
||||||
// Stop watching the file
|
assert(prev.ino <= 0);
|
||||||
fs.unwatchFile(enoentFile);
|
// Stop watching the file
|
||||||
}
|
fs.unwatchFile(enoentFile);
|
||||||
}, 2));
|
}
|
||||||
|
}, 2));
|
||||||
|
|
||||||
|
watcher.start(); // should not crash
|
||||||
|
|
||||||
// Watch events should callback with a filename on supported systems.
|
// Watch events should callback with a filename on supported systems.
|
||||||
// Omitting AIX. It works but not reliably.
|
// Omitting AIX. It works but not reliably.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user