mirror of
https://github.com/rui314/mold.git
synced 2026-11-09 04:49:33 -10:00
Report a failed link when SIGCHLD is ignored
An ignored SIGCHLD is inherited across exec, e.g. from `trap '' CHLD` in a shell. The child that fork_child creates is then reaped automatically, so the parent's waitpid fails with ECHILD. The parent ignored that and read the untouched zero status as a successful exit, so a link that failed exited with status 0. Report a failure instead. Also read and write the completion byte through File, which removes two raw libc calls. Based on https://github.com/rui314/mold/pull/1682.
This commit is contained in:
1 parent
fd13e83077
commit
25d2a3ecf1
2 files changed
+25
-9
No files matched your search
+14
-9
@@ -2,7 +2,11 @@
|
||||
//! handling for disk-full errors, and the `-run` subcommand.
|
||||
|
||||
#[cfg(not(windows))]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
|
||||
use std::fs::File;
|
||||
#[cfg(not(windows))]
|
||||
use std::io::{Read, Write};
|
||||
#[cfg(not(windows))]
|
||||
use std::os::unix::io::{FromRawFd, OwnedFd};
|
||||
#[cfg(not(windows))]
|
||||
use std::sync::Mutex;
|
||||
|
||||
@@ -38,12 +42,17 @@ pub fn fork_child() {
|
||||
if pid > 0 {
|
||||
// Parent
|
||||
drop(writer);
|
||||
let mut buf = [0u8; 1];
|
||||
if libc::read(reader.as_raw_fd(), buf.as_mut_ptr().cast(), 1) == 1 {
|
||||
if File::from(reader).read_exact(&mut [0u8]).is_ok() {
|
||||
libc::_exit(0);
|
||||
}
|
||||
|
||||
// If SIGCHLD is ignored, which is inherited across exec, the
|
||||
// child is reaped automatically and waitpid fails. Its exit
|
||||
// status is lost then, so report a failure.
|
||||
let mut status = 0;
|
||||
libc::waitpid(pid, &raw mut status, 0);
|
||||
if libc::waitpid(pid, &raw mut status, 0) == -1 {
|
||||
libc::_exit(1);
|
||||
}
|
||||
if libc::WIFEXITED(status) {
|
||||
libc::_exit(libc::WEXITSTATUS(status));
|
||||
}
|
||||
@@ -67,11 +76,7 @@ pub fn notify_parent() {
|
||||
let Some(writer) = PIPE_WRITER.lock().unwrap().take() else {
|
||||
return;
|
||||
};
|
||||
let buf = [1u8];
|
||||
// SAFETY: writer owns a valid pipe write end.
|
||||
unsafe {
|
||||
libc::write(writer.as_raw_fd(), buf.as_ptr().cast(), 1);
|
||||
}
|
||||
let _ = File::from(writer).write_all(&[1]);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
. $(dirname $0)/common.inc
|
||||
|
||||
cat <<EOF | $CC -o $t/a.o -c -xc -
|
||||
int foo();
|
||||
int main() { return foo(); }
|
||||
EOF
|
||||
|
||||
# An ignored SIGCHLD is inherited across exec. The forked child is then
|
||||
# reaped automatically, but mold must still report that the link failed.
|
||||
(trap '' CHLD; not ./mold -o $t/exe $t/a.o)
|
||||
Reference in new issue
Block a user