diff --git a/core/Cargo.lock b/core/Cargo.lock index 6514b5c5..1c648364 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.7.31-alpha" +version = "1.7.32-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index 37f93996..edc724e3 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.7.31-alpha" +version = "1.7.32-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/core/archipelago/src/main.rs b/core/archipelago/src/main.rs index 97495fba..21f73be7 100644 --- a/core/archipelago/src/main.rs +++ b/core/archipelago/src/main.rs @@ -229,5 +229,14 @@ async fn main() -> Result<()> { crash_recovery::remove_pid_marker(&config.data_dir).await; info!("Archipelago shut down cleanly"); - Ok(()) + + // Hard-exit after logging. All business state is persisted by now + // (connections drained, PID marker removed, disk flushes done via + // tokio::fs awaits). Letting tokio try to drop the runtime instead + // can stall for 15s+ on non-daemon OS threads we don't directly + // own (mdns_sd daemon, reqwest resolver pool, etc.) — long enough + // for systemd's TimeoutStopSec to SIGKILL us and mark the service + // Failed, which makes an otherwise-successful update look like a + // crash in `systemctl status`. + std::process::exit(0); } diff --git a/core/archipelago/src/transport/lan.rs b/core/archipelago/src/transport/lan.rs index 73265839..610948e7 100644 --- a/core/archipelago/src/transport/lan.rs +++ b/core/archipelago/src/transport/lan.rs @@ -160,6 +160,18 @@ impl LanTransport { } } +impl Drop for LanTransport { + // The mdns_sd daemon runs on its own OS thread and the browse + // listener task blocks on a sync channel. Without this call both + // keep the process alive past SIGTERM, long enough for systemd to + // SIGKILL us — which makes a normal update look like a crash. + fn drop(&mut self) { + if let Some(daemon) = self.daemon.take() { + let _ = daemon.shutdown(); + } + } +} + impl NodeTransport for LanTransport { fn kind(&self) -> TransportKind { TransportKind::Lan