summaryrefslogtreecommitdiffstats
path: root/src/transport/mycelium.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/mycelium.rs')
-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 3a08b76..d31925d 100644
--- a/src/transport/mycelium.rs
+++ b/src/transport/mycelium.rs
@@ -269,15 +269,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")