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 diff --git a/releases/manifest.json b/releases/manifest.json index faeaa5cd..acea168f 100644 --- a/releases/manifest.json +++ b/releases/manifest.json @@ -1,28 +1,26 @@ { - "version": "1.7.31-alpha", + "version": "1.7.32-alpha", "release_date": "2026-04-22", "changelog": [ - "Installing IndeedHub is now fully self-healing — if a previous install was interrupted, re-running from the App Store automatically cleans up the leftover containers and tries again instead of failing with a 'name already in use' error.", - "New default app registries and update mirrors now appear automatically on existing nodes after an update — no more needing to manually add Server 3 (OVH) from the settings page. Anything you've explicitly removed stays removed.", - "Fixed the 'Test' button on registries that protect their API endpoint — it used to falsely report those registries as unreachable. It now correctly recognizes a protected-but-alive registry as reachable.", - "First-boot cleanup: removed an old IndeedHub stub from the first-boot script that used to race the main installer and occasionally leave a half-installed IndeedHub behind." + "Critical fix: the v1.7.31-alpha frontend package shipped with the wrong archive layout, which caused the web UI to return 403/500 after the update landed. v1.7.32-alpha ships the frontend correctly — nodes that got stuck on the 403 page will auto-recover on this update.", + "Shutdown fix: updates no longer briefly show the archipelago service as 'Failed' in systemd. The old version was logging 'shut down cleanly' but leaving a background mDNS thread alive, so systemd would force-kill it 15 seconds later and mark the unit failed. The process now exits promptly after saving its state." ], "components": [ { "name": "archipelago", - "current_version": "1.7.30-alpha", - "new_version": "1.7.31-alpha", - "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.31-alpha/archipelago", - "sha256": "ce2f899d3c4b615136223ae6295ee4b5de4009d1db926f7648a788c0ad3c84b8", - "size_bytes": 40786728 + "current_version": "1.7.31-alpha", + "new_version": "1.7.32-alpha", + "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.32-alpha/archipelago", + "sha256": "f5c0d51a3235b7619ac5b71140abd07b04cc90555205a4c0416c8c8c4a9a4588", + "size_bytes": 40791792 }, { - "name": "archipelago-frontend-1.7.31-alpha.tar.gz", - "current_version": "1.7.30-alpha", - "new_version": "1.7.31-alpha", - "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.31-alpha/archipelago-frontend-1.7.31-alpha.tar.gz", - "sha256": "00f474725edaf14dc41d0c02abd3afcff1b30fa50846adec9e11b3c5b2188564", - "size_bytes": 77008771 + "name": "archipelago-frontend-1.7.32-alpha.tar.gz", + "current_version": "1.7.31-alpha", + "new_version": "1.7.32-alpha", + "download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.32-alpha/archipelago-frontend-1.7.32-alpha.tar.gz", + "sha256": "1eb1deaf479538f0552f395fc1aea67b1a247ddef6bfbf436353ba1997eac1be", + "size_bytes": 77008678 } ] } diff --git a/releases/v1.7.32-alpha/archipelago b/releases/v1.7.32-alpha/archipelago new file mode 100755 index 00000000..e0caf9cb Binary files /dev/null and b/releases/v1.7.32-alpha/archipelago differ diff --git a/releases/v1.7.32-alpha/archipelago-frontend-1.7.32-alpha.tar.gz b/releases/v1.7.32-alpha/archipelago-frontend-1.7.32-alpha.tar.gz new file mode 100644 index 00000000..d6481a0b Binary files /dev/null and b/releases/v1.7.32-alpha/archipelago-frontend-1.7.32-alpha.tar.gz differ