diff options
author | James M Snell <jasnell@gmail.com> | 2021-07-20 18:24:30 +0300 |
---|---|---|
committer | Daniel Bevenius <daniel.bevenius@gmail.com> | 2021-07-22 08:09:03 +0300 |
commit | f1d353398e147edb944e94c75ab6764ac6aaf81f (patch) | |
tree | b12fb2d61d939066c529a724d798467cbd8e1635 /src/node_file.cc | |
parent | 71b2df253d015dcb526af9fc1fb4ca21893a8d24 (diff) |
fs: check closing_ in FileHandle::Close
Fix possible flaky failure. Keep uv_fs_close from being called twice
on the same fd.
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/39472
Refs: https://github.com/nodejs/node/issues/39464
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Diffstat (limited to 'src/node_file.cc')
-rw-r--r-- | src/node_file.cc | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/node_file.cc b/src/node_file.cc index 906109e121a..350e66b6e42 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -215,6 +215,7 @@ FileHandle::TransferData::TransferData(int fd) : fd_(fd) {} FileHandle::TransferData::~TransferData() { if (fd_ > 0) { uv_fs_t close_req; + CHECK_NE(fd_, -1); CHECK_EQ(0, uv_fs_close(nullptr, &close_req, fd_, nullptr)); uv_fs_req_cleanup(&close_req); } @@ -237,8 +238,9 @@ BaseObjectPtr<BaseObject> FileHandle::TransferData::Deserialize( // JS during GC. If closing the fd fails at this point, a fatal exception // will crash the process immediately. inline void FileHandle::Close() { - if (closed_) return; + if (closed_ || closing_) return; uv_fs_t req; + CHECK_NE(fd_, -1); int ret = uv_fs_close(env()->event_loop(), &req, fd_, nullptr); uv_fs_req_cleanup(&req); @@ -384,6 +386,7 @@ MaybeLocal<Promise> FileHandle::ClosePromise() { close->Resolve(); } }}; + CHECK_NE(fd_, -1); int ret = req->Dispatch(uv_fs_close, fd_, AfterClose); if (ret < 0) { req->Reject(UVException(isolate, ret, "close")); @@ -555,8 +558,13 @@ ShutdownWrap* FileHandle::CreateShutdownWrap(Local<Object> object) { } int FileHandle::DoShutdown(ShutdownWrap* req_wrap) { + if (closing_ || closed_) { + req_wrap->Done(0); + return 1; + } FileHandleCloseWrap* wrap = static_cast<FileHandleCloseWrap*>(req_wrap); closing_ = true; + CHECK_NE(fd_, -1); wrap->Dispatch(uv_fs_close, fd_, uv_fs_callback_t{[](uv_fs_t* req) { FileHandleCloseWrap* wrap = static_cast<FileHandleCloseWrap*>( FileHandleCloseWrap::from_req(req)); |