summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-21 14:14:15 +0200
committertv <tv@krebsco.de>2026-10-21 14:14:15 +0200
commita2815e3eec7f080ae44e7b43ba697bd0cc13da08 (patch)
tree41905cb488f528adfbf0fb9947080b92c22bd56d
parentc9279e4907ceb3cab2abd3ad6e62d011d7d8a1c2 (diff)
let linux signal supervised mycelium when we die
-rw-r--r--src/transport/mycelium.rs30
1 files changed, 22 insertions, 8 deletions
diff --git a/src/transport/mycelium.rs b/src/transport/mycelium.rs
index d2deebe..9147a5d 100644
--- a/src/transport/mycelium.rs
+++ b/src/transport/mycelium.rs
@@ -280,15 +280,29 @@ impl SupervisedMycelium {
let mut cmd = Command::new("mycelium");
let fds_to_inherit: Vec<i32> = [node_fd, net_fd].iter().filter_map(|&x| x).collect();
- if !fds_to_inherit.is_empty() {
- unsafe {
- cmd.pre_exec(move || {
- for &fd in &fds_to_inherit {
- libc::fcntl(fd, libc::F_SETFD, 0);
+ // The child must never outlive us. An orphaned Mycelium keeps running with our
+ // key; the next one we start then shares its address, and replies (including
+ // Mycelium's own message ACKs) go to whichever instance the routers picked,
+ // leaving our messages pending forever. Drop only runs on a clean shutdown, so
+ // let the kernel signal the child when we die, however we die.
+ let parent_pid = std::process::id() as libc::pid_t;
+ unsafe {
+ cmd.pre_exec(move || {
+ for &fd in &fds_to_inherit {
+ libc::fcntl(fd, libc::F_SETFD, 0);
+ }
+ #[cfg(target_os = "linux")]
+ {
+ if libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) != 0 {
+ return Err(std::io::Error::last_os_error());
}
- Ok(())
- });
- }
+ // We may have died between fork and prctl.
+ if libc::getppid() != parent_pid {
+ libc::_exit(1);
+ }
+ }
+ Ok(())
+ });
}
cmd.arg("--key-file")