Could replace the `timeoutcmd` module with a custom `timeout` command implementation
The following seems to work well enough and is much simpler than the timeoutcmd module.
use std::{
ffi::OsString,
process::Command,
thread::{sleep, spawn},
time::Duration,
};
use clap::Parser;
use libc::{SIGKILL, kill};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
let mut cmd = Command::new(&args.argv0);
cmd.args(&args.args);
let mut child = cmd.spawn()?;
let child_pid = i32::try_from(child.id())?;
let timeout = args.timeout;
let _handler = spawn(move || terminate_after(timeout, child_pid));
child.wait()?;
Ok(())
}
fn terminate_after(t: Duration, child: i32) {
sleep(t);
unsafe {
kill(child, SIGKILL);
}
eprintln!("kill child process {child} for taking too long");
}
/// Run a command, but terminate it if takes too long.
#[derive(Debug, Parser)]
struct Args {
/// Maximum duration, in seconds, how long the command may take.
#[clap(value_parser = parse_duration)]
timeout: Duration,
/// Name of command to run.
argv0: OsString,
/// Arguments to command.
args: Vec<OsString>,
}
fn parse_duration(arg: &str) -> Result<Duration, std::num::ParseIntError> {
let seconds = arg.parse()?;
Ok(std::time::Duration::from_secs(seconds))
}