The dev-mode tests stop the server they start #417
No reviewers
Labels
No labels
bug
contract
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/iw-cli!417
Loading…
Reference in a new issue
No description provided.
Delete branch "fix-orphaned-dev-servers"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The defect
Each E2E run leaked up to 14 dashboard JVMs. 41 were alive on the development
machine, orphaned onto init, holding their ports and 3.9 GB of RAM. The
oldest had run for 37 hours.
./iw dashboardreaches the server JVM through a chain:iwandiw-runuseexec, so a signal reachesscala-cli.scala-clidoesnot pass it to the JVM it started, and
LiveCommandEnv.startServerAndBlockstarts the server with
ProcessBuilderand blocks onwaitFor(). The testskilled the launcher PID, so the server never learned that its parent had died.
The suite-level net did not work either.
teardownran:No process has that string in its command line. The server's command line is
java -jar out.jar <state> <port> <hosts> --dev. This is the same defect theIW-345 review recorded for
dashboard-dev-gate.bats, which was never corrected.teardownthen ranrm -rf /tmp/iw-dev-*— which deleted the state directory ofthe still-running orphan, and would also delete the directory of a developer's
live
./iw dashboard --devsession.The fix
start_dev_serverlaunches undersetsid, so the whole launcher chain gets itsown process group.
stop_dev_serversignals that group, so the server dies withits launcher, and removes only the
/tmp/iw-dev-<timestamp>directory of theserver it started.
The pair replaces the launch-poll-kill block that was copied into all 12 tests,
together with
register_worktreefor the registration call they share: 417 linesdeleted, 112 added. The duplication is why one wrong kill was repeated 14 times.
dashboard-dev-gate.batshad the same defect in its teardown — it removed/tmp/iw-dev-gate-*, which nothing creates, and leaked two directories per run.Its
GATE_SERVER_PIDguard was never assigned to.Verification
The new test
stopping the dev server leaves no server process behindstarts adev server, waits for its health endpoint, stops it, and asserts with
pgrepthatno JVM holds its state file. It fails on the old kill path (verified before
the fix, with an orphan left behind) and passes on the new one.
The first version of that test was a false pass: it killed at the "Port:" line,
which the launcher prints before it spawns the server, so there was nothing to
orphan. The health wait is what makes it a real reproduction.
Gate: E2E 177 BATS tests, 0 failures (full run captured and counted).
After the run: 0 orphaned servers, 0 leftover
/tmp/iw-dev-*directories —against up to 14 orphans before.
setsidandpgrepwere confirmed present inthe CI image.
Not included
The product-side change I first proposed — a JVM shutdown hook in
startServerAndBlock— is not here. It would not have fixed this: the signalstops at
scala-cliand never reaches the JVM that would run the hook. Thepaths that matter are already correct — Ctrl+C signals the whole foreground
group, and
./iw server startis a managed daemon with a PID file. Adding thehook would be code that fixes nothing demonstrable.
🤖 Generated with Claude Code