Skip to content
47 changes: 47 additions & 0 deletions src/io/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,14 @@ pub mod closer {
pub struct Closer {
pub(crate) fd: Fd,
task: WorkPoolTask,
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
scheduled_from: bun_core::StoredTrace,
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
scheduled_on_tid: i64,
/// What the fd pointed at when the close was scheduled (empty if it
/// was already closed by then).
Comment on lines +2241 to +2242

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code

#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
scheduled_description: bun_sys::close_ledger::FdDescription,
}

#[cfg(not(windows))]
Expand All @@ -2243,6 +2251,39 @@ pub mod closer {
unsafe impl bun_threading::work_pool::OwnedTask for Closer {
fn run(self: Box<Self>) {
use bun_sys::FdExt;
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
{
#[allow(clippy::print_stderr)]
if let Some(err) = self.fd.close_allowing_bad_file_descriptor(None) {
if err.errno == bun_sys::E::EBADF as _ {
std::eprintln!(
"\n==================== Closer: close({}) = EBADF ====================",
self.fd.native()
);
std::eprintln!(
"when this Closer was scheduled the fd was \"{}\" (empty = already closed at that point)",
self.scheduled_description.as_str()
);
std::eprintln!(
"this Closer was scheduled on tid {} at:",
self.scheduled_on_tid
);
bun_core::dump_stack_trace(
&self.scheduled_from.trace(),
bun_core::DumpStackTraceOptions::default(),
);
std::eprintln!(
"======================================================================\n"
);
panic!(
"Closer: fd {} was already closed when the async close ran (see report above)",
self.fd.native()
);
}
}
return;
}
#[allow(unreachable_code)]
self.fd.close();
}
}
Expand All @@ -2258,6 +2299,12 @@ pub mod closer {
node: Default::default(),
callback: <Self as bun_threading::work_pool::OwnedTask>::__callback,
},
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
scheduled_from: bun_core::StoredTrace::capture(None),
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
scheduled_on_tid: bun_sys::close_ledger::current_tid(),
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
scheduled_description: bun_sys::close_ledger::FdDescription::of(fd.native()),
}));
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/io/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ impl PollOrFd {
#[cfg(windows)]
let _ = close_fd;
let fd = self.get_fd();
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
if fd != Fd::INVALID {
bun_sys::close_ledger::record_registration_event(
match (self.tag_name(), close_fd) {
("poll", true) => "close_impl(poll, close_fd)",
("poll", false) => "close_impl(poll, keep fd)",
(_, true) => "close_impl(bare fd, close_fd)",
(_, false) => "close_impl(bare fd, keep fd)",
},
fd.native(),
);
}
#[cfg(target_os = "macos")]
let mut close_async = true;
#[cfg(all(not(target_os = "macos"), not(windows)))]
Expand Down
65 changes: 62 additions & 3 deletions src/io/posix_event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,9 +667,37 @@ impl FilePoll {
let ctl = unsafe { linux::epoll_ctl(watcher_fd, op, fd.native(), &raw mut event) };
self.flags.insert(Flags::WasEverRegistered);
if let Some(errno) = errno_sys(ctl, sys::Tag::epoll_ctl) {
#[cfg(debug_assertions)]
{
let what = std::format!(
"epoll_ctl({}, fd {}, {}) failed: {} (poll flags before: {})",
if op == EPOLL::CTL_MOD {
"CTL_MOD"
} else {
"CTL_ADD"
},
fd.native(),
<&'static str>::from(flag),
errno
.as_ref()
.err()
.and_then(|e| core::str::from_utf8(e.name()).ok())
.unwrap_or("?"),
FlagsFormatter(self.flags),
);
sys::close_ledger::report_fd_event(&what, fd.native());
}
self.deactivate(loop_);
return errno;
}
#[cfg(debug_assertions)]
{
// Only ADDs create kernel registrations; MODs are noise here.
if op == EPOLL::CTL_ADD {
let what = std::format!("ADD ok ({})", <&'static str>::from(flag));
sys::close_ledger::record_registration_event(&what, fd.native());
}
}
}
#[cfg(target_os = "macos")]
{
Expand Down Expand Up @@ -923,6 +951,15 @@ impl FilePoll {
|| self.flags.contains(Flags::PollMachport)
|| self.flags.contains(Flags::PollMemoryPressure))
{
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
sys::close_ledger::record_registration_event(
if force_unregister {
"DEL skipped(force): no poll flags"
} else {
"DEL skipped: no poll flags"
},
fd.native(),
);
// no-op
return sys::Result::Ok(());
}
Expand Down Expand Up @@ -961,6 +998,8 @@ impl FilePoll {
self.flags.remove(Flags::PollWritable);
self.flags.remove(Flags::PollMachport);
self.flags.remove(Flags::PollMemoryPressure);
#[cfg(all(debug_assertions, any(target_os = "linux", target_os = "android")))]
sys::close_ledger::record_registration_event("DEL skipped: needs_rearm", fd.native());
return sys::Result::Ok(());
}

Expand All @@ -983,9 +1022,29 @@ impl FilePoll {
};

match sys::get_errno(ctl) {
sys::E::SUCCESS => {}
e if deregistration_already_gone(e) => {}
e => return sys::Result::Err(sys::Error::from_code(e, sys::Tag::epoll_ctl)),
sys::E::SUCCESS => {
#[cfg(debug_assertions)]
sys::close_ledger::record_registration_event("DEL ok", fd.native());
}
e if deregistration_already_gone(e) => {
#[cfg(debug_assertions)]
sys::close_ledger::record_registration_event(
if e == sys::E::EBADF {
"DEL -> EBADF (fd already closed)"
} else {
"DEL -> ENOENT (not registered)"
},
fd.native(),
);
}
e => {
#[cfg(debug_assertions)]
sys::close_ledger::record_registration_event(
"DEL failed (other errno)",
fd.native(),
);
return sys::Result::Err(sys::Error::from_code(e, sys::Tag::epoll_ctl));
}
}
}
#[cfg(target_os = "macos")]
Expand Down
Loading
Loading