in reverie-process/src/exit_status.rs [159:207]
fn run_forked<F>(f: F) -> nix::Result<ExitStatus>
where
F: FnOnce() -> nix::Result<()>,
{
match unsafe { fork() }? {
ForkResult::Parent { child, .. } => {
// Simply wait for the child to exit.
match waitpid(child, None)? {
WaitStatus::Exited(_, code) => Ok(ExitStatus::Exited(code)),
WaitStatus::Signaled(_, sig, coredump) => {
Ok(ExitStatus::Signaled(sig, coredump))
}
wait_status => unreachable!("Got unexpected wait status: {:?}", wait_status),
}
}
ForkResult::Child => {
// Suppress core dumps for testing purposes.
let limit = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
unsafe {
// restore some sighandlers to default
for &sig in &[libc::SIGALRM, libc::SIGINT, libc::SIGVTALRM] {
libc::signal(sig, libc::SIG_DFL);
}
// disable coredump
libc::setrlimit(libc::RLIMIT_CORE, &limit)
};
// Run the child.
let code = match f() {
Ok(()) => 0,
Err(err) => {
eprintln!("{}", err);
1
}
};
// The closure should have called `exit` by this point, but just
// in case it didn't, call it ourselves.
//
// Note: We also can't use the normal exit function here because we
// don't want to call atexit handlers since `execve` was never
// called.
unsafe { ::libc::_exit(code) };
}
}
}