◐ Shell
clean mode source ↗

src: show original file name in FileHandle GC close errors · nodejs/node@a31ad37

@@ -222,9 +222,12 @@ void FSReqBase::MemoryInfo(MemoryTracker* tracker) const {

222222

// collection if necessary. If that happens, a process warning will be

223223

// emitted (or a fatal exception will occur if the fd cannot be closed.)

224224

FileHandle::FileHandle(BindingData* binding_data,

225-

Local<Object> obj, int fd)

225+

Local<Object> obj,

226+

int fd,

227+

std::string original_name)

226228

: AsyncWrap(binding_data->env(), obj, AsyncWrap::PROVIDER_FILEHANDLE),

227229

StreamBase(env()),

230+

original_name_(std::move(original_name)),

228231

fd_(fd),

229232

binding_data_(binding_data) {

230233

MakeWeak();

@@ -234,6 +237,7 @@ FileHandle::FileHandle(BindingData* binding_data,

234237

FileHandle* FileHandle::New(BindingData* binding_data,

235238

int fd,

236239

Local<Object> obj,

240+

std::string original_name,

237241

std::optional<int64_t> maybeOffset,

238242

std::optional<int64_t> maybeLength) {

239243

Environment* env = binding_data->env();

@@ -242,7 +246,7 @@ FileHandle* FileHandle::New(BindingData* binding_data,

242246

.ToLocal(&obj)) {

243247

return nullptr;

244248

}

245-

auto handle = new FileHandle(binding_data, obj, fd);

249+

auto handle = new FileHandle(binding_data, obj, fd, original_name);

246250

if (maybeOffset.has_value()) handle->read_offset_ = maybeOffset.value();

247251

if (maybeLength.has_value()) handle->read_length_ = maybeLength.value();

248252

return handle;

@@ -274,6 +278,7 @@ void FileHandle::New(const FunctionCallbackInfo<Value>& args) {

274278

FileHandle::New(binding_data,

275279

args[0].As<Int32>()->Value(),

276280

args.This(),

281+

{},

277282

maybeOffset,

278283

maybeLength);

279284

}

@@ -293,6 +298,7 @@ int FileHandle::DoWrite(WriteWrap* w,

293298294299

void FileHandle::MemoryInfo(MemoryTracker* tracker) const {

295300

tracker->TrackField("current_read", current_read_);

301+

tracker->TrackField("original_name", original_name_);

296302

}

297303298304

BaseObject::TransferMode FileHandle::GetTransferMode() const {

@@ -344,9 +350,13 @@ inline void FileHandle::Close() {

344350

FS_SYNC_TRACE_END(close);

345351

uv_fs_req_cleanup(&req);

346352347-

struct err_detail { int ret; int fd; };

353+

struct err_detail {

354+

int ret;

355+

int fd;

356+

std::string name;

357+

};

348358349-

err_detail detail { ret, fd_ };

359+

err_detail detail{ret, fd_, original_name_};

350360351361

AfterClose();

352362

@@ -362,25 +372,30 @@ inline void FileHandle::Close() {

362372

// down the process is the only reasonable thing we can do here.

363373

env()->SetImmediate([detail](Environment* env) {

364374

HandleScope handle_scope(env->isolate());

375+

static constexpr std::string_view unknown_path = "<unknown path>";

376+

std::string_view filename =

377+

detail.name.empty() ? unknown_path : detail.name;

365378366379

// If there was an error while trying to close the file descriptor,

367380

// we will throw that instead.

368381

if (detail.ret < 0) {

369-

char msg[70];

370-

snprintf(msg,

371-

arraysize(msg),

372-

"Closing file descriptor %d on garbage collection failed",

373-

detail.fd);

382+

auto formatted = SPrintF(

383+

"Closing file descriptor %d on garbage collection failed (%s)",

384+

detail.fd,

385+

filename);

374386

HandleScope handle_scope(env->isolate());

375-

env->ThrowUVException(detail.ret, "close", msg);

387+

env->ThrowUVException(detail.ret, "close", formatted.c_str());

376388

return;

377389

}

378390379391

THROW_ERR_INVALID_STATE(

380392

env,

381393

"A FileHandle object was closed during garbage collection. "

382394

"This used to be allowed with a deprecation warning but is now "

383-

"considered an error. Please close FileHandle objects explicitly.");

395+

"considered an error. Please close FileHandle objects explicitly. "

396+

"File descriptor: %d (%s)",

397+

detail.fd,

398+

filename);

384399

});

385400

}

386401

@@ -824,8 +839,8 @@ void AfterOpenFileHandle(uv_fs_t* req) {

824839

FS_ASYNC_TRACE_END1(

825840

req->fs_type, req_wrap, "result", static_cast<int>(req->result))

826841

if (after.Proceed()) {

827-

FileHandle* fd = FileHandle::New(req_wrap->binding_data(),

828-

static_cast<int>(req->result));

842+

FileHandle* fd = FileHandle::New(

843+

req_wrap->binding_data(), static_cast<int>(req->result), {}, req->path);

829844

if (fd == nullptr) return;

830845

req_wrap->Resolve(fd->object());

831846

}

@@ -2222,7 +2237,7 @@ static void OpenFileHandle(const FunctionCallbackInfo<Value>& args) {

22222237

if (result < 0) {

22232238

return; // syscall failed, no need to continue, error info is in ctx

22242239

}

2225-

FileHandle* fd = FileHandle::New(binding_data, result);

2240+

FileHandle* fd = FileHandle::New(binding_data, result, {}, path.ToString());

22262241

if (fd == nullptr) return;

22272242

args.GetReturnValue().Set(fd->object());

22282243

}