Skip to content

fix(deploy): boot-test cleanup can't match a Next server's rewritten process title - #832

Merged
catomean merged 1 commit into
mainfrom
fix/boot-test-cleanup-pkill
Aug 29, 2026
Merged

fix(deploy): boot-test cleanup can't match a Next server's rewritten process title#832
catomean merged 1 commit into
mainfrom
fix/boot-test-cleanup-pkill

Conversation

@catomean

Copy link
Copy Markdown
Collaborator

Summary

Found while auditing the box for 0.0.0.0-bound services: a leaked boot-test instance was squatting on port 4099 (OC_BOOT_PORT), actively serving 500s from a stale build, with no systemd unit, no owner.

Root cause, verified with an isolated local reproduction — not just reasoned about: Next's standalone server rewrites its own process title to next-server (v...) during startup, and that rewrite changes the process's actual /proc/PID/cmdline, not just what ps displays. pkill -f 'app-next/server.js' matches against that same cmdline, so once the server finishes booting — routinely before the cleanup line runs, since the health-check loop can take up to 20s — there's nothing left to match.

Confirmed both directions:

  • pkill -f fails to kill a title-rewritten process (reproduced)
  • fuser -k <port>/tcp kills it every time (reproduced)

Why this matters

Not cosmetic — a leaked boot-test process silently threatens every subsequent deploy: the next boot-test's health check can hit the stale leaked process instead of the new build, or fail outright on a port collision. Either way a deploy could report success (or a confusing failure) without ever actually testing the new code.

Fix

fuser -k "$BOOT/tcp" instead — kills whatever is actually listening on the scratch port, independent of what the process calls itself.

Verified

  • Local repro: confirmed the exact failure and the exact fix, isolated from the real box
  • Killed the actual leaked instance on the box manually as part of this investigation

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Y9rKLxddothnXEtY6KDziN

…xt server

Found 2026-08-29 auditing the box for services bound to 0.0.0.0: a leaked
boot-test instance was squatting on port 4099, actively serving 500s from
a stale build, with no systemd unit, no owner, alive since an earlier deploy.

Root cause, verified with an isolated reproduction (not just reasoned about):
Next's standalone server rewrites its own process title to "next-server
(v...)" during startup, and — confirmed by reading /proc/PID/cmdline
directly, both on the box and in a minimal local repro — that rewrite
changes the process's actual argv as seen by /proc, not just what `ps`
displays. `pkill -f 'app-next/server.js'` matches against that same argv,
so once the server finishes booting (routinely before this line runs, since
the health-check loop above can take up to 20s), there is nothing left
containing "app-next/server.js" to match. Confirmed both directions in the
repro: pkill -f fails to kill a title-rewritten process; fuser -k on the
actual bound port kills it every time.

This is not cosmetic. A leaked boot-test process on $OC_BOOT_PORT silently
threatens every subsequent deploy: the next boot-test's own health check can
hit the STALE process instead of the new build, or fail outright on a port
collision — either way, a deploy could report success (or a confusing
failure) without ever having actually tested the new code.

Replaced with `fuser -k "$BOOT/tcp"` — kills whatever is actually listening
on the scratch port, independent of what the process calls itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y9rKLxddothnXEtY6KDziN
@catomean
catomean merged commit 07885c9 into main Aug 29, 2026
6 checks passed
@catomean
catomean deleted the fix/boot-test-cleanup-pkill branch August 29, 2026 06:16
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