release(v1.7.8-alpha): fix apply ETXTBSY — use mv instead of install
apply_update's binary swap called `sudo install -m 0755 src /usr/local/bin/archipelago`. install opens the destination for write with O_TRUNC; the kernel returns ETXTBSY (exit 1) when the path is a currently-running executable, which it always is during apply because apply_update is called by the archipelago RPC handler — running as archipelago itself. Every previous "Failed to apply update" was this one root cause; the manual sideload path only worked because we stopped the service first. rename() doesn't modify the file it replaces — it repoints the path at a new inode while the old inode stays alive for any process that has it mapped. `mv` uses rename(). Switched to `sudo mv` (with prior chmod+chown on the staging file) so the swap is atomic and tolerant of the running binary. Frontend tarball byte-identical to v1.7.7-alpha; only the binary version string changes. Artefacts: archipelago 2753daec…48094d 40377648 archipelago-frontend-1.7.8-alpha.tar.gz 4fb79664…0172e9 76984615 (reused) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
23cc78f0db
commit
cbf30e2e29
2
core/Cargo.lock
generated
2
core/Cargo.lock
generated
@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.7-alpha"
|
version = "1.7.8-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"archipelago-container",
|
"archipelago-container",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "archipelago"
|
name = "archipelago"
|
||||||
version = "1.7.7-alpha"
|
version = "1.7.8-alpha"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Archipelago Bitcoin Node OS - Native backend"
|
description = "Archipelago Bitcoin Node OS - Native backend"
|
||||||
authors = ["Archipelago Team"]
|
authors = ["Archipelago Team"]
|
||||||
|
|||||||
@ -277,27 +277,31 @@ pub async fn apply_update(data_dir: &Path) -> Result<()> {
|
|||||||
|
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
"archipelago" => {
|
"archipelago" => {
|
||||||
// /usr/local/bin is root-owned; archipelago user can't
|
// We're running FROM /usr/local/bin/archipelago right now,
|
||||||
// fs::copy into it directly. Use sudo install which handles
|
// so we can't rewrite it in place — `install` / `cp` would
|
||||||
// the copy, mode, and ownership atomically.
|
// hit ETXTBSY on the busy executable. Use `mv` instead:
|
||||||
|
// rename() is atomic and doesn't modify the existing file,
|
||||||
|
// it just re-points the path at a new inode. The currently
|
||||||
|
// running process keeps executing off the old inode; new
|
||||||
|
// invocations (i.e. after the post-apply systemctl
|
||||||
|
// restart) pick up the new binary.
|
||||||
|
let staged = src.to_string_lossy().to_string();
|
||||||
|
let _ = tokio::process::Command::new("sudo")
|
||||||
|
.args(["chmod", "0755", &staged])
|
||||||
|
.status()
|
||||||
|
.await;
|
||||||
|
let _ = tokio::process::Command::new("sudo")
|
||||||
|
.args(["chown", "root:root", &staged])
|
||||||
|
.status()
|
||||||
|
.await;
|
||||||
let status = tokio::process::Command::new("sudo")
|
let status = tokio::process::Command::new("sudo")
|
||||||
.args([
|
.args(["mv", &staged, "/usr/local/bin/archipelago"])
|
||||||
"install",
|
|
||||||
"-m",
|
|
||||||
"0755",
|
|
||||||
"-o",
|
|
||||||
"root",
|
|
||||||
"-g",
|
|
||||||
"root",
|
|
||||||
&src.to_string_lossy(),
|
|
||||||
"/usr/local/bin/archipelago",
|
|
||||||
])
|
|
||||||
.status()
|
.status()
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("Failed to spawn install for {}", name))?;
|
.with_context(|| format!("Failed to spawn mv for {}", name))?;
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"sudo install failed for {} (exit {:?})",
|
"sudo mv failed for {} (exit {:?})",
|
||||||
name,
|
name,
|
||||||
status.code()
|
status.code()
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.7-alpha",
|
"version": "1.7.8-alpha",
|
||||||
"release_date": "2026-04-20",
|
"release_date": "2026-04-20",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Over-the-air update test — no feature changes, just a version bump so your node can walk through the whole update flow end-to-end using the new robust installer. Safe to apply; nothing to do afterwards."
|
"Install Update finally works end-to-end over the air. The installer was trying to overwrite the running backend binary with a tool that fails on in-use files (ETXTBSY) — swapped it for an atomic rename, which the kernel allows on a live executable. Every previous 'Failed to apply update' attempt was this one root cause."
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"name": "archipelago",
|
"name": "archipelago",
|
||||||
"current_version": "1.7.6-alpha",
|
"current_version": "1.7.7-alpha",
|
||||||
"new_version": "1.7.7-alpha",
|
"new_version": "1.7.8-alpha",
|
||||||
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.7-alpha/archipelago",
|
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.8-alpha/archipelago",
|
||||||
"sha256": "e3f1740dcb008a6fcef1adc7f2c9d2f86bfa8d5397e9b8f425260977c7006025",
|
"sha256": "2753daec113bb4fbbc2a68148ef1579524a26707733eea410faf400b9948094d",
|
||||||
"size_bytes": 40373392
|
"size_bytes": 40377648
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "archipelago-frontend-1.7.7-alpha.tar.gz",
|
"name": "archipelago-frontend-1.7.8-alpha.tar.gz",
|
||||||
"current_version": "1.7.6-alpha",
|
"current_version": "1.7.7-alpha",
|
||||||
"new_version": "1.7.7-alpha",
|
"new_version": "1.7.8-alpha",
|
||||||
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.7-alpha/archipelago-frontend-1.7.7-alpha.tar.gz",
|
"download_url": "https://git.tx1138.com/lfg2025/archy/raw/branch/main/releases/v1.7.8-alpha/archipelago-frontend-1.7.8-alpha.tar.gz",
|
||||||
"sha256": "4fb796643cc9dc8469078ca3392f7cc5541071f6849979922b3259e5f20172e9",
|
"sha256": "4fb796643cc9dc8469078ca3392f7cc5541071f6849979922b3259e5f20172e9",
|
||||||
"size_bytes": 76984615
|
"size_bytes": 76984615
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
releases/v1.7.8-alpha/archipelago
Executable file
BIN
releases/v1.7.8-alpha/archipelago
Executable file
Binary file not shown.
BIN
releases/v1.7.8-alpha/archipelago-frontend-1.7.8-alpha.tar.gz
Normal file
BIN
releases/v1.7.8-alpha/archipelago-frontend-1.7.8-alpha.tar.gz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user