Prevent terminated e2e runs from leaking tmux - #849
Conversation
roborev: Combined Review (
|
The first shutdown hardening still registered some children only after readiness, let individual fresh servers remove a shared socket root, and could stop listening for signals before normal tmux cleanup completed. Those gaps left termination races where a starting child, a late socket, or a second signal could still strand test resources. Keep process ownership from spawn through exit, signal all owned servers before sweeping and retry after exit, preserve failed cleanup roots, reject stale resources owned by another local user, and keep Go signal handling active until tracked tmux servers are gone. Review context: roborev-ci PR #849 comment 5200866219 and local roborev jobs 10213 and 10214. PID reuse does not add cross-platform process-start introspection: it can only delay recovery, while incomplete owner files are written before any child or tmux socket can exist. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
roborev: Combined Review (
|
roborev: Combined Review (
|
A terminated go run wrapper could exit while its compiled e2e server stayed alive. The runner then lost the child process it needed to stop, so tmux cleanup could finish while the real server was still running. Build one run-owned server binary before Playwright starts and share it with every worker. Keep explicit binaries externally owned, and bind generated-binary cleanup to the process that built it so a terminated worker cannot remove the binary from its siblings. Review context: roborev-ci PR #849 comment 5206859932. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
Playwright workers can exit before their e2e servers finish, while the root runner previously had no shared ownership record to stop it from deleting their tmux socket root. The e2e server could also admit a new tmux session while its one-shot private-server kill was starting. Publish child ownership across workers, close session admission before tmux teardown, and keep signal-driven runner exit reliable when cleanup reports an error. This keeps late sockets discoverable until every admitted creator and owned server has stopped. Review outcomes for roborev-ci comment #849 (comment): - Fixed: the root runner now waits for worker-published server processes before removing the shared tmux directory. - Fixed: signal cleanup reports failures and exits from a finally block. - User: not an issue — forced teardown must proceed after bounded handler draining; active handlers may fail after their resources are destroyed. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
roborev: Combined Review (
|
The first shutdown hardening still registered some children only after readiness, let individual fresh servers remove a shared socket root, and could stop listening for signals before normal tmux cleanup completed. Those gaps left termination races where a starting child, a late socket, or a second signal could still strand test resources. Keep process ownership from spawn through exit, signal all owned servers before sweeping and retry after exit, preserve failed cleanup roots, reject stale resources owned by another local user, and keep Go signal handling active until tracked tmux servers are gone. Review context: roborev-ci PR #849 comment 5200866219 and local roborev jobs 10213 and 10214. PID reuse does not add cross-platform process-start introspection: it can only delay recovery, while incomplete owner files are written before any child or tmux socket can exist. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
A terminated go run wrapper could exit while its compiled e2e server stayed alive. The runner then lost the child process it needed to stop, so tmux cleanup could finish while the real server was still running. Build one run-owned server binary before Playwright starts and share it with every worker. Keep explicit binaries externally owned, and bind generated-binary cleanup to the process that built it so a terminated worker cannot remove the binary from its siblings. Review context: roborev-ci PR #849 comment 5206859932. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
Playwright workers can exit before their e2e servers finish, while the root runner previously had no shared ownership record to stop it from deleting their tmux socket root. The e2e server could also admit a new tmux session while its one-shot private-server kill was starting. Publish child ownership across workers, close session admission before tmux teardown, and keep signal-driven runner exit reliable when cleanup reports an error. This keeps late sockets discoverable until every admitted creator and owned server has stopped. Review outcomes for roborev-ci comment #849 (comment): - Fixed: the root runner now waits for worker-published server processes before removing the shared tmux directory. - Fixed: signal cleanup reports failures and exits from a finally block. - User: not an issue — forced teardown must proceed after bounded handler draining; active handlers may fail after their resources are destroyed. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
02e1d3b to
d46e9ec
Compare
roborev: Combined Review (
|
roborev: Combined Review (
|
Daemonized tmux servers can outlive both Go and Playwright runners, while the previous cleanup ran late during graceful shutdown or only fired a signal without waiting. Abruptly terminated test runs therefore accumulated private sessions and sockets on developer and CI hosts. Make the test runner's ownership boundary recoverable across SIGTERM, timeouts, and prior crashed runs. Tmux teardown now happens before potentially blocking drains, child shutdown is bounded with escalation, and a later run can reap socket roots whose owner no longer exists. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
The first shutdown hardening still registered some children only after readiness, let individual fresh servers remove a shared socket root, and could stop listening for signals before normal tmux cleanup completed. Those gaps left termination races where a starting child, a late socket, or a second signal could still strand test resources. Keep process ownership from spawn through exit, signal all owned servers before sweeping and retry after exit, preserve failed cleanup roots, reject stale resources owned by another local user, and keep Go signal handling active until tracked tmux servers are gone. Review context: roborev-ci PR #849 comment 5200866219 and local roborev jobs 10213 and 10214. PID reuse does not add cross-platform process-start introspection: it can only delay recovery, while incomplete owner files are written before any child or tmux socket can exist. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
Concurrent fresh-server stops and repeated termination signals could release process ownership or unlink the shared socket root while another child was still exiting. Go test helpers also registered tmux only after daemonization, leaving a signal window where cleanup could miss a live server. Keep ownership through observed exit, preserve the root during pre-exit sweeps, verify stale sockets before removal, and serialize Go tmux startup with cleanup. A real Node owner to Go server to workspace tmux regression now exercises the complete signal path. Review context: local roborev jobs 10231 and 10232. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
Global shutdown could empty its ownership registries before children exited, allowing overlapping cleanup to remove the shared tmux root beneath a live process. A forced-stop timeout and an ambiguous tmux list error could also be mistaken for confirmed cleanup. Serialize overlapping shutdown, keep every child registered until exit is observed, and accept only the explicit no-server result before clearing Go tracking. This keeps failed resources recoverable instead of silently forgetting them. Review context: local roborev job 10241. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
A terminated go run wrapper could exit while its compiled e2e server stayed alive. The runner then lost the child process it needed to stop, so tmux cleanup could finish while the real server was still running. Build one run-owned server binary before Playwright starts and share it with every worker. Keep explicit binaries externally owned, and bind generated-binary cleanup to the process that built it so a terminated worker cannot remove the binary from its siblings. Review context: roborev-ci PR #849 comment 5206859932. Generated with Codex (gpt-5.6-sol) Co-authored-by: Codex <noreply@openai.com>
Playwright workers can exit before their e2e servers finish, while the root runner previously had no shared ownership record to stop it from deleting their tmux socket root. The e2e server could also admit a new tmux session while its one-shot private-server kill was starting. Publish child ownership across workers, close session admission before tmux teardown, and keep signal-driven runner exit reliable when cleanup reports an error. This keeps late sockets discoverable until every admitted creator and owned server has stopped. Review outcomes for roborev-ci comment #849 (comment): - Fixed: the root runner now waits for worker-published server processes before removing the shared tmux directory. - Fixed: signal cleanup reports failures and exits from a finally block. - User: not an issue — forced teardown must proceed after bounded handler draining; active handlers may fail after their resources are destroyed. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
GitHub pull-request jobs use a detached merge checkout whose version-control status probe can fail after checkout credentials are removed. The Chromium and Firefox jobs therefore stopped while building the direct e2e server, before Playwright could start. The run-owned test binary does not publish build version metadata. Disable Go VCS stamping for that disposable build so its result does not depend on checkout metadata. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
The e2e runner deliberately uses a missing tmux executable when a test must select the in-process PTY owner. Wrapping that path in the shutdown gate made it appear executable, so backend detection chose tmux and the kitty-keyboard browser test failed on every retry. Leave the intentional no-tmux mode unwrapped. Ordinary e2e states still use the creation gate, while PTY-owner tests keep the unavailable-command signal that selects their required backend. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
Windows retains an exited process object while a handle remains open. The daemon CLI killed a verified process but kept the handle returned by FindProcess, so lifecycle commands treated the terminated PID as alive until their 70-second timeout. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
43f16c9 to
f3971fa
Compare
roborev: Combined Review (
|
Terminated e2e runners can leave daemonized tmux servers behind because tmux outlives its parent, while ordinary defers, exit callbacks, and late graceful cleanup are skipped or cut short by signals.\n\n- Stop each Go e2e server's private tmux server before bounded handler draining, including reset and termination paths.\n- Track Playwright-owned children from spawn through confirmed exit, preserve the shared socket root while a child can still create tmux state, and keep repeated SIGINT/SIGTERM handling active during cleanup.\n- Build one run-owned e2e-server binary before Playwright starts, share it with every worker, and let only the builder remove it. This keeps the real server process in the runner's signal path instead of a go run wrapper.\n- Sweep sockets before and after child exit, removing stale sockets only when tmux verifies their server is gone and retaining ambiguous failures for recovery.\n- Synchronize Go test tmux startup with signal cleanup so termination cannot land between daemonization and ownership registration.\n- Recover dead-owner directories only when their resources belong to the current local user. Developer tmux servers remain outside the cleanup boundary.\n\ngenerated by a clanker