cargo-test still fails on main after #8464: tier1_every_ffi_type_against_test_dylib aborts on Linux with
thread '<unnamed>' panicked at library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
thread caused non-unwinding panic. aborting.
Measured on the scheduled sweep of 15a30d7f6 (run 32353180323), which contains #8464 — so the closure-dispatch conversion did not fix this.
Where it actually aborts. The captured stdout stops right after external-terminated: 2 and never reaches closed-throws: — the step that deliberately throws:
lib.close();
try { s.ffi_i32_add1(1); } catch (e: any) { closedError = String(e && e.message); }
console.log("closed-throws:", closedError.includes("close()"));
That throw originates in bun_ffi::dlopen::invoke_from_closure, which calls throw_error_with_code("bun:ffi: symbol … was called after close() …"). It is reached through the per-arity stubs generated by sym_thunk!:
extern "C" fn $name(closure: *const ClosureHeader $(, $a: f64)*) -> f64 {
unsafe { invoke_from_closure(closure, &args) }
}
Those stubs are extern "C", i.e. nounwind, so the unwind hits Rust's abort-on-unwind shim inside the thunk itself. #8464 made the closure-dispatch callers unwind-capable; these thunks are the callees it could not see — a call through an extern "C-unwind" function pointer does not remove the callee's own nounwind guard.
close_thunk has the same shape: it takes a Mutex and unwrap()s, and a poison panic there would abort identically.
Fix: generate both as extern "C-unwind" (PR #8479).
Process note worth recording. #8464 was merged while its own e2e-scoped job — the Linux run of exactly this suite, which the PR deliberately opted into by naming the test file — was still in flight; merging cancelled it (run 32340796570, job cancelled at 08:52). The check that would have caught this was destroyed by the merge. macOS passes this test with and without either fix, so the Linux e2e-scoped result is the only verdict, and it must be allowed to report before merging.
cargo-teststill fails onmainafter #8464:tier1_every_ffi_type_against_test_dylibaborts on Linux withMeasured on the scheduled sweep of
15a30d7f6(run 32353180323), which contains #8464 — so the closure-dispatch conversion did not fix this.Where it actually aborts. The captured stdout stops right after
external-terminated: 2and never reachesclosed-throws:— the step that deliberately throws:That throw originates in
bun_ffi::dlopen::invoke_from_closure, which callsthrow_error_with_code("bun:ffi: symbol … was called after close() …"). It is reached through the per-arity stubs generated bysym_thunk!:Those stubs are
extern "C", i.e. nounwind, so the unwind hits Rust's abort-on-unwind shim inside the thunk itself. #8464 made the closure-dispatch callers unwind-capable; these thunks are the callees it could not see — a call through anextern "C-unwind"function pointer does not remove the callee's own nounwind guard.close_thunkhas the same shape: it takes aMutexandunwrap()s, and a poison panic there would abort identically.Fix: generate both as
extern "C-unwind"(PR #8479).Process note worth recording. #8464 was merged while its own
e2e-scopedjob — the Linux run of exactly this suite, which the PR deliberately opted into by naming the test file — was still in flight; merging cancelled it (run 32340796570, job cancelled at 08:52). The check that would have caught this was destroyed by the merge. macOS passes this test with and without either fix, so the Linuxe2e-scopedresult is the only verdict, and it must be allowed to report before merging.