#![cfg(unix)]
extern "C" {
fn kill(pid: i32, sig: i32) -> i32;
fn setsid() -> i32;
}
pub fn send_signal(pid: i32, sig: i32) -> i32 {
unsafe { kill(pid, sig) }
}
pub(crate) unsafe fn new_session() -> i32 {
setsid()
}
#[cfg(test)]
mod tests {
use super::*;
extern "C" {
fn fork() -> i32;
fn waitpid(pid: i32, status: *mut i32, options: i32) -> i32;
}
#[test]
fn new_session_succeeds_in_a_forked_child() {
unsafe {
let pid = fork();
assert!(pid >= 0, "fork failed");
if pid == 0 {
let sid = new_session();
std::process::exit(if sid >= 0 { 0 } else { 1 });
}
let mut status: i32 = 0;
let reaped = waitpid(pid, &mut status as *mut i32, 0);
assert_eq!(reaped, pid, "waitpid did not reap our child");
let exited_normally = (status & 0x7f) == 0;
let exit_code = (status >> 8) & 0xff;
assert!(
exited_normally && exit_code == 0,
"child setsid failed: raw status {status}"
);
}
}
}