fix(client): install upgrade binaries via install(1), not cp — avoids ETXTBSY #301

Merged
clawdie merged 1 commit from fix-upgrade-text-file-busy into main 2026-06-29 08:07:06 +02:00
Owner

Fixes the 'Text file busy' (ETXTBSY) bug osa found during the live FreeBSD upgrade test.

Root cause

cmd_upgrade installed binaries with sudo cp. cp opens the destination O_TRUNC — truncating the inode of the currently-running colibri client as it overwrites itself. FreeBSD refuses writes to a busy text (executable) inode → ETXTBSY. Linux tolerates it, which is why it only showed on FreeBSD.

Fix

Use install -m 0755 instead of cp. install(1) writes a temp file in the target dir and rename(2)s it into place. Rename swaps the directory entry; the live process keeps its old mapped inode until it exits. No write to the busy inode → no ETXTBSY. Portable: same behavior on FreeBSD and Linux, and order-independent (no daemon-stop sequencing needed).

Supersedes fix/colibri-text-file-busy

That branch reordered the installs (client before daemon stop). Two problems:

  1. It does not compilebuild_dir is used before its let declaration (E0425). The green test results were from the already-installed #296 binary, not a build of that branch.
  2. Even compiled, the reorder would not fix it: the client is still running while it cps over itself, so cp still truncates the busy inode regardless of order relative to the daemon stop.

Please close fix/colibri-text-file-busy in favor of this.

Gates

  • cargo fmt --all --check clean; cargo clippy -p colibri-client --all-targets -- -D warnings clean.

Credit: osa found the bug on FreeBSD. Refs #295/#296.

🤖 Generated with Claude Code

Fixes the 'Text file busy' (ETXTBSY) bug osa found during the live FreeBSD upgrade test. ### Root cause `cmd_upgrade` installed binaries with `sudo cp`. `cp` opens the destination `O_TRUNC` — truncating the inode of the **currently-running `colibri` client** as it overwrites itself. FreeBSD refuses writes to a busy text (executable) inode → ETXTBSY. Linux tolerates it, which is why it only showed on FreeBSD. ### Fix Use `install -m 0755` instead of `cp`. `install(1)` writes a temp file in the target dir and `rename(2)`s it into place. Rename swaps the directory entry; the live process keeps its old mapped inode until it exits. No write to the busy inode → no ETXTBSY. Portable: same behavior on FreeBSD and Linux, and **order-independent** (no daemon-stop sequencing needed). ### Supersedes `fix/colibri-text-file-busy` That branch reordered the installs (client before daemon stop). Two problems: 1. **It does not compile** — `build_dir` is used before its `let` declaration (E0425). The green test results were from the already-installed #296 binary, not a build of that branch. 2. Even compiled, the reorder would not fix it: the client is still running while it `cp`s over itself, so `cp` still truncates the busy inode regardless of order relative to the daemon stop. Please close `fix/colibri-text-file-busy` in favor of this. ### Gates - `cargo fmt --all --check` clean; `cargo clippy -p colibri-client --all-targets -- -D warnings` clean. Credit: osa found the bug on FreeBSD. Refs #295/#296. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(client): install upgrade binaries via install(1), not cp — avoids ETXTBSY
Some checks failed
CI / rust (pull_request) Has been cancelled
CI / markdown (pull_request) Has been cancelled
CI / port (pull_request) Has been cancelled
CI / agent-jail-pkgs (pull_request) Has been cancelled
5bfd77069d
colibri upgrade overwrote its own running client binary with sudo cp, which
truncates the busy text inode and fails with 'Text file busy' (ETXTBSY) on
FreeBSD. install(1) writes a temp file in the target dir then rename(2)s it
into place, so the live process keeps its old mapped inode and the swap
succeeds on both FreeBSD and Linux — order-independent, no daemon-stop
sequencing needed.

Supersedes fix/colibri-text-file-busy (reorder approach: did not compile —
build_dir used before declaration — and would not have fixed the client
self-overwrite since cp still truncates the busy inode regardless of order).

Found by osa during the live FreeBSD upgrade test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
clawdie deleted branch fix-upgrade-text-file-busy 2026-06-29 08:07:13 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
clawdie/colibri!301
No description provided.