children die when rss dies via PR_SET_PDEATHSIG

sets SIGTERM death signal in each child before exec, so if the
daemon exits (even by crash/SIGKILL), all managed services receive
SIGTERM and terminate. adds libc dependency for prctl.
This commit is contained in:
Niko Marmeladkov 2026-07-03 14:14:02 +03:00
parent a92768157c
commit 4c62bded4d
3 changed files with 25 additions and 14 deletions

1
Cargo.lock generated
View file

@ -346,6 +346,7 @@ version = "0.1.0"
dependencies = [
"chrono",
"clap",
"libc",
"nix",
"serde",
"toml",

View file

@ -9,3 +9,4 @@ serde = { version = "1", features = ["derive"] }
toml = "0.8"
chrono = "0.4"
nix = { version = "0.29", default-features = false, features = ["signal", "fs"] }
libc = "0.2"

View file

@ -3,6 +3,7 @@ use std::fs;
use std::io::{BufRead, BufReader, Write};
use std::os::unix::fs::PermissionsExt;
use std::os::unix::net::{UnixListener, UnixStream};
use std::os::unix::process::CommandExt;
use std::process::{Child, Command, Stdio};
use std::time::{Duration, SystemTime};
use std::sync::atomic::{AtomicBool, Ordering};
@ -165,20 +166,28 @@ fn spawn(name: &str, cfg: &ServiceConfig) -> Option<Proc> {
let log_path = log_path.to_string_lossy().to_string();
let cmd = cfg.resolve_command(name, &log_path);
let mut child = match Command::new("sh")
.arg("-c")
.arg(&cmd)
.current_dir(&cfg.workdir)
.envs(&cfg.env)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(Stdio::null())
.spawn()
{
Ok(c) => c,
Err(e) => {
append_log(&log_path, &format!("E: spawn failed: {}", e));
return None;
let mut child = {
let mut sh = Command::new("sh");
sh.arg("-c")
.arg(&cmd)
.current_dir(&cfg.workdir)
.envs(&cfg.env)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(Stdio::null());
// SAFETY: pre_exec runs in the child after fork; minimal ops only
unsafe {
sh.pre_exec(|| {
libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM);
Ok(())
});
}
match sh.spawn() {
Ok(c) => c,
Err(e) => {
append_log(&log_path, &format!("E: spawn failed: {}", e));
return None;
}
}
};