Skip to content

fix(install): replace binaries atomically to avoid macOS SIGKILL on upgrade - #797

Merged
AbirAbbas merged 1 commit into
mainfrom
fix/install-atomic-binary-replace
Jul 18, 2026
Merged

fix(install): replace binaries atomically to avoid macOS SIGKILL on upgrade#797
AbirAbbas merged 1 commit into
mainfrom
fix/install-atomic-binary-replace

Conversation

@AbirAbbas

@AbirAbbas AbirAbbas commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Problem

Re-running the install script over an existing installation left af unrunnable on macOS — every invocation died with zsh: killed af (SIGKILL), including the script's own --version verification step. Confusingly, codesign --verify on the installed binary passed.

Root cause: install_binary used cp to overwrite the existing binary in place, reusing the same inode. When the old binary has a live process at overwrite time (e.g. af server running during a curl | bash upgrade — the common case), the macOS kernel's cached per-vnode code-signing state is invalidated, and the path becomes permanently poisoned: every subsequent exec is either SIGKILLed or hangs in uninterruptible wait (U state, immune to kill -9), even though the on-disk signature verifies clean.

Verified locally (Darwin 24.6.0, arm64)

  • cp over an idle binary (same or different content): fine — no poisoning.
  • cp over a binary while a process was executing it: reproduced — subsequent execs hang in uninterruptible kernel wait; the poisoning persists after the old process dies.
  • Applying this PR's stage+mv replacement to the poisoned path: fixed — next exec runs normally (fresh inode clears the kernel's cached state).
  • Fresh installs and upgrades via the new stage+mv path: run correctly.

Fix

Stage the binary to a temp file in the install dir and mv it into place. Rename gives upgrades a fresh inode and is atomic, so there is no window where the binary is missing and no in-place write to a mapped file. Applied to both copy sites:

  • install_binary — the agentfield CLI binary
  • install_tray — the af-tray binary (same latent bug; the tray force-restarts on update, so an upgrade over a running tray would hit it)

Workaround for already-broken installs

codesign -f -s - ~/.agentfield/bin/agentfield (re-sign in place), or delete the file and reinstall with the fixed script. Processes already hung in U state clear on reboot.

🤖 Generated with Claude Code

…pgrade

cp onto an existing binary reuses the inode, which poisons the macOS
kernel's cached code-signature state for that vnode. Every exec after an
upgrade is then killed with SIGKILL ("zsh: killed af") even though
codesign --verify passes on disk. Stage to a temp file and mv into place
so upgrades always land on a fresh inode. Applies to both the agentfield
binary and the af-tray binary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AbirAbbas
AbirAbbas requested a review from a team as a code owner July 18, 2026 19:26
@AbirAbbas
AbirAbbas merged commit 1a55ddc into main Jul 18, 2026
21 checks passed
@AbirAbbas
AbirAbbas deleted the fix/install-atomic-binary-replace branch July 18, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant