timely_util/util/
process_util.rs

1/*
2    Process management
3*/
4
5use nix::sys::wait::{waitpid, WaitStatus};
6use nix::unistd::{fork, ForkResult};
7use std::process::exit;
8
9// Run a function as a separate process.
10// If it crashes or is terminated, finish gracefully.
11// This function may panic if the system calls fail or the process
12// has an unexpected result (e.g. stopped, continued, nonzero exit code).
13pub fn run_as_process<Out, F: FnOnce() -> Out>(func: F) {
14    match unsafe { fork() } {
15        Ok(ForkResult::Parent { child, .. }) => {
16            println!("[parent] running in subprocess PID: {}", child);
17            match waitpid(child, None) {
18                Ok(WaitStatus::Exited(pid, code)) => {
19                    debug_assert!(child == pid);
20                    if code != 0 {
21                        println!("[parent] non-zero exit code! {}", code);
22                    }
23                }
24                Ok(WaitStatus::Signaled(pid, signal, code)) => {
25                    debug_assert!(child == pid);
26                    println!(
27                        "[parent] process killed! signal {}, exit code {}",
28                        signal, code
29                    );
30                }
31                Ok(status) => panic!(
32                    "[parent] Error: unexpected child process status! {:?}",
33                    status
34                ),
35                Err(err) => panic!("[parent] Error: waitpid failed! {}", err),
36            }
37        }
38        Ok(ForkResult::Child) => {
39            // println!("[child] starting");
40            func();
41            // println!("[child] exiting");
42            exit(0)
43        }
44        Err(err) => panic!("[parent] Error: fork failed! {}", err),
45    }
46}