Skip to content

Instantly share code, notes, and snippets.

@oconnor663
Created May 1, 2025 00:04
Show Gist options
  • Save oconnor663/73266d2e552c3d9ef6e1e9259c58bfab to your computer and use it in GitHub Desktop.
Save oconnor663/73266d2e552c3d9ef6e1e9259c58bfab to your computer and use it in GitHub Desktop.
waitpid vs waitid race condition demo (It's not a good idea for WNOWAIT to race against reaping)
use std::io;
use std::process::Command;
use std::thread;
pub fn waitpid(id: u32) -> io::Result<i32> {
let mut status = 0i32;
let ret = unsafe { libc::waitpid(id as i32, &mut status, 0) };
if ret != -1 {
Ok(status)
} else {
Err(io::Error::last_os_error())
}
}
pub fn wait_without_reaping(id: u32) -> io::Result<()> {
let ret = unsafe {
let mut siginfo = std::mem::zeroed();
libc::waitid(libc::P_PID, id, &mut siginfo, libc::WEXITED | libc::WNOWAIT)
};
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
fn main() {
let child = Command::new("sleep").arg("0.1").spawn().unwrap();
let id = child.id();
let mut handles = Vec::new();
for i in 0..3 {
handles.push(thread::spawn(move || {
eprintln!("waitid {i} {:?}", wait_without_reaping(id));
}));
}
for i in 0..3 {
handles.push(thread::spawn(move || {
eprintln!("waitpid {i} {:?}", waitpid(id));
}));
}
for handle in handles {
handle.join().unwrap();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment