From 39ea21410d65926ad2385a00f0f03edb0ae0b552 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 20 Jul 2021 08:24:30 -0700 Subject: [PATCH] fs: check closing_ in FileHandle::Close Fix possible flaky failure. Keep uv_fs_close from being called twice on the same fd. Refs: https://github.com/nodejs/node/issues/39464 Signed-off-by: James M Snell --- src/node_file.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/node_file.cc b/src/node_file.cc index 906109e121ae82..350e66b6e426b8 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 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 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) { } int FileHandle::DoShutdown(ShutdownWrap* req_wrap) { + if (closing_ || closed_) { + req_wrap->Done(0); + return 1; + } FileHandleCloseWrap* wrap = static_cast(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::from_req(req));