wait for children and report return code #37

Merged
JakeHillion merged 1 commits from await-children into main 2022-05-19 16:56:42 +01:00
2 changed files with 49 additions and 8 deletions

View File

@ -17,17 +17,19 @@ use std::path::Path;
use nix::fcntl::OFlag; use nix::fcntl::OFlag;
use nix::sys::socket; use nix::sys::socket;
use nix::unistd; use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
use nix::unistd::{self, Pid};
pub struct RunArgs<'a> { pub struct RunArgs<'a> {
pub spec: Option<&'a Path>, pub spec: Option<&'a Path>,
pub debug: bool, pub debug: bool,
pub daemon: bool,
pub binary: &'a Path, pub binary: &'a Path,
pub binary_args: Vec<&'a str>, pub binary_args: Vec<&'a str>,
} }
pub fn run(args: &RunArgs) -> Result<()> { pub fn run(args: &RunArgs) -> Result<i32> {
// parse the specification // parse the specification
let spec: Specification = if let Some(m) = args.spec { let spec: Specification = if let Some(m) = args.spec {
if m.extension().map(|e| e == "json") == Some(true) { if m.extension().map(|e| e == "json") == Some(true) {
@ -62,7 +64,41 @@ pub fn run(args: &RunArgs) -> Result<()> {
} }
.spawn()?; .spawn()?;
Ok(()) if args.daemon {
return Ok(exitcode::OK);
}
info!("spawned successfully, awaiting children exiting...");
let mut exit_code = exitcode::OK;
loop {
let status = match waitpid(Some(Pid::from_raw(-1)), Some(WaitPidFlag::WEXITED)) {
Ok(v) => Ok(v),
Err(nix::Error::ECHILD) => {
info!("all child processes have exited, exiting...");
break;
}
Err(e) => Err(Error::Nix {
msg: "waitpid",
src: e,
}),
}?;
match status {
WaitStatus::Exited(pid, code) => {
if code != exitcode::OK {
exit_code = code;
}
debug!("child {} exited with code {}", pid, code);
}
WaitStatus::Signaled(pid, sig, _coredump) => {
debug!("child {} was terminated with signal {}", pid, sig);
}
_ => unreachable!(),
}
}
Ok(exit_code)
} }
fn create_pipes(names: Vec<&str>) -> Result<HashMap<String, PipePair>> { fn create_pipes(names: Vec<&str>) -> Result<HashMap<String, PipePair>> {

View File

@ -1,4 +1,4 @@
use log::{error, info}; use log::error;
use clone_shim::{run, RunArgs}; use clone_shim::{run, RunArgs};
@ -34,6 +34,13 @@ fn main() {
.help("Stop each spawned application process so that it can be attached to.") .help("Stop each spawned application process so that it can be attached to.")
.takes_value(false), .takes_value(false),
) )
.arg(
Arg::new("daemon")
.long("daemon")
.short('D')
.help("Detach the shim from all child processes and exit immediately.")
.takes_value(false),
)
.arg( .arg(
Arg::new("binary") Arg::new("binary")
.index(1) .index(1)
@ -69,15 +76,13 @@ fn main() {
let args = RunArgs { let args = RunArgs {
spec: matches.value_of("spec").map(Path::new), spec: matches.value_of("spec").map(Path::new),
debug: matches.is_present("debug"), debug: matches.is_present("debug"),
daemon: matches.is_present("daemon"),
binary, binary,
binary_args, binary_args,
}; };
match run(&args) { match run(&args) {
Ok(_) => { Ok(_) => exitcode::OK,
info!("launched successfully");
exitcode::OK
}
Err(e) => { Err(e) => {
error!("error: {}", e); error!("error: {}", e);
-1 -1