Remove the temporary output file on a panic

A panic aborts the process in release builds, skipping the cleanup that
a fatal error or a SIGSEGV/SIGBUS does, so a failed link left its
.<output>.<pid> file behind. Install a panic hook that removes the file
and then calls the default hook, so the panic message, backtrace and
abort stay as they were. The hook runs on the panicking thread, so it
also covers rayon workers and the extern "C" LTO plugin callbacks.
This commit is contained in:
Rui Ueyama committed 2026-09-30 23:13:53 +09:00
1 parent 3d7bed0abd
commit a0d62d97f7
3 files changed
+18 -1

No files matched your search

+1
View File
@@ -99,6 +99,7 @@ pub fn link<E: Target>(cmdline: Cmdline) -> LinkResult {
let t_all = ctx.timer("all");
crate::subprocess::install_signal_handler();
error::install_panic_hook();
// Fork a subprocess unless --no-fork is given.
if ctx.args.fork {
+11
View File
@@ -114,6 +114,17 @@ pub fn exit_after_cleanup(status: i32) -> ! {
std::process::exit(status)
}
/// Makes a panic remove a partially-written output file, as a fatal error
/// does, before the default hook reports the panic. Nothing recovers from
/// a panic, so it always terminates the process.
pub fn install_panic_hook() {
let default_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
crate::output_file::cleanup();
default_hook(info);
}));
}
#[macro_export]
macro_rules! fatal {
($($arg:tt)*) => {
+6 -1
View File
@@ -27,4 +27,9 @@ off=$(readelf -SW $t/a.o | sed 's/\[ *[0-9]*\]//' |
# past the 8-byte section.
printf '\0\1\0\0\0\0\0\0' | dd of=$t/a.o bs=1 seek=$((16#$off)) conv=notrunc status=none
not $CC -B. -o $t/exe $t/a.o $t/b.o >& /dev/null
# mold panics on this input. The panic must not leave the temporary
# output file behind.
rm -rf $t/out
mkdir $t/out
not $CC -B. -o $t/out/exe $t/a.o $t/b.o >& /dev/null
[ -z "$(ls -A $t/out)" ]