diff --git a/synit-pid1/Cargo.toml b/synit-pid1/Cargo.toml index 60c0708..9c67875 100644 --- a/synit-pid1/Cargo.toml +++ b/synit-pid1/Cargo.toml @@ -19,5 +19,5 @@ syndicate-macros = "0.4.1" clap = "3.0.0-beta.2" clap_generate = "3.0.0-beta.2" nix = "^0.22" -tokio = { version = "1.10.0", features = ["process"] } +tokio = { version = "1.10.0", features = ["process", "signal"] } tracing = "0.1.14" diff --git a/synit-pid1/dockertest/.gitignore b/synit-pid1/dockertest/.gitignore new file mode 100644 index 0000000..158dade --- /dev/null +++ b/synit-pid1/dockertest/.gitignore @@ -0,0 +1,2 @@ +syndicate-server +synit-pid1 diff --git a/synit-pid1/dockertest/Dockerfile b/synit-pid1/dockertest/Dockerfile new file mode 100644 index 0000000..77b50ae --- /dev/null +++ b/synit-pid1/dockertest/Dockerfile @@ -0,0 +1,5 @@ +FROM alpine:latest +ADD ./synit-pid1 . +ADD ./syndicate-server . +ENV RUST_LOG=debug +ENTRYPOINT /synit-pid1 --server-path /syndicate-server diff --git a/synit-pid1/dockertest/go b/synit-pid1/dockertest/go new file mode 100755 index 0000000..99ae592 --- /dev/null +++ b/synit-pid1/dockertest/go @@ -0,0 +1,11 @@ +#!/bin/sh + +(cd ..; cross build --target x86_64-unknown-linux-musl) & +make -C ../../../syndicate-rs static & +wait + +cp -a ../target/x86_64-unknown-linux-musl/debug/synit-pid1 . +cp -a ../../../syndicate-rs/target/x86_64-unknown-linux-musl/debug/syndicate-server . + +docker build -t synit . +docker run -it --rm synit diff --git a/synit-pid1/src/main.rs b/synit-pid1/src/main.rs index 3f538e5..dec057f 100644 --- a/synit-pid1/src/main.rs +++ b/synit-pid1/src/main.rs @@ -1,5 +1,9 @@ use clap::Clap; +use nix::sys::signal::{killpg, Signal}; +use nix::sys::wait; +use nix::unistd; + use std::sync::Arc; use syndicate::actor::*; @@ -9,6 +13,8 @@ use syndicate::value::NestedValue; use syndicate::value::Value; use tokio::process; +use tokio::select; +use tokio::signal::unix::{signal, SignalKind}; #[derive(Clap, Clone, Debug)] #[clap(version)] @@ -32,15 +38,64 @@ impl Pid1Listener { impl Entity for Pid1Listener { } +async fn handle_sigchld_and_waitpid() -> Result<(), Box> { + let mut sigchlds = signal(SignalKind::child())?; + let mut sigints = signal(SignalKind::interrupt())?; + let mut sigterms = signal(SignalKind::terminate())?; + + tracing::info!("Awaiting signals..."); + loop { + select! { + _ = sigchlds.recv() => { + loop { + match wait::waitpid(None, Some(wait::WaitPidFlag::WNOHANG)) { + Ok(wait::WaitStatus::StillAlive) => { + tracing::debug!("No child processes to reap at this time"); + break; + } + Ok(status) => + tracing::debug!("Child process reaped: {:?}", status), + Err(nix::errno::Errno::ECHILD) => { + tracing::debug!("waitpid(2) yielded ECHILD"); + break; + } + Err(e) => + Err(e)?, + } + } + } + _ = sigints.recv() => { + tracing::debug!("Received SIGINT"); + let result = killpg(unistd::getpgrp(), Some(Signal::SIGINT)); + tracing::debug!("killpg result: {:?}", result); + break; + } + _ = sigterms.recv() => { + tracing::debug!("Received SIGTERM"); + let result = killpg(unistd::getpgrp(), Some(Signal::SIGTERM)); + tracing::debug!("killpg result: {:?}", result); + break; + } + } + } + + Ok(()) +} + #[tokio::main] async fn main() -> Result<(), Box> { syndicate::convenient_logging()?; - match nix::unistd::setsid() { + match unistd::setsid() { Ok(_pid) => tracing::info!("setsid(2): new session is {}", _pid), Err(e) => tracing::info!("setsid(2) failed: {:?}", &e), } + match unistd::setpgid(unistd::Pid::from_raw(0), unistd::Pid::from_raw(0)) { + Ok(()) => tracing::info!("setpgid(2) succeeded"), + Err(e) => tracing::info!("setpgid(2) failed: {:?}", &e), + } + let config = Arc::new(CommandLine::parse()); let server = process::Command::new(&config.server_path) @@ -68,7 +123,9 @@ async fn main() -> Result<(), Box> { .underlying; t.assert(ds, Value::simple_record1("pid1", AnyValue::domain(Cap::new(&listener))).wrap()); Ok(()) - }).await??; + }); + + handle_sigchld_and_waitpid().await?; Ok(()) }