Skip to content

Fix with_server.py server hangs, orphaned processes, and silent failures#1400

Open
j0usa-commits wants to merge 1 commit into
anthropics:mainfrom
j0usa-commits:fix/with-server-cleanup-and-logging
Open

Fix with_server.py server hangs, orphaned processes, and silent failures#1400
j0usa-commits wants to merge 1 commit into
anthropics:mainfrom
j0usa-commits:fix/with-server-cleanup-and-logging

Conversation

@j0usa-commits

Copy link
Copy Markdown

Summary

Fixes three bugs in webapp-testing/scripts/with_server.py, the helper that starts dev servers, waits for them to be ready, runs a test command, and cleans up.

1. Chatty servers freeze mid-run

Server output went to subprocess.PIPE, but the pipes were never read. Once a server logged ~64KB (about a thousand log lines), its next write blocked on the full pipe buffer and the server stopped responding entirely. Any per-request logger triggers this — npm run dev, vite, Flask debug mode, Python's http.server.

  • Before: a stock http.server under a 3,000-request client froze at ~1,100 requests; the client timed out.
  • After: server output goes to a temp log file (writes never block); all 3,000 requests complete.

2. Cleanup leaves the real server running

With shell=True, process.terminate() killed only the wrapper shell — the actual server survived with the port still bound. The next run then found the port open, reported "ready," and silently ran tests against the stale server. This happens with the docstring's own recommended usage (--server "cd backend && python server.py").

  • Before: after "All servers stopped," the port still accepted connections and the server process was alive.
  • After: servers start in their own process group (start_new_session=True) and cleanup signals the whole group (SIGTERM, then SIGKILL after 5s); the port is released and no process remains. Non-POSIX platforms keep the old terminate/kill behavior.

3. Startup failures hid the server's error

A server that crashed on boot wrote its error to the never-read pipe, so users saw only Server failed to start on port X within 30s.

  • Before: a server exiting with FATAL: missing DATABASE_URL config produced just the generic timeout error.
  • After: the error message includes the tail of the server's log, showing the FATAL line.

Three related fixes to webapp-testing's with_server.py:

1. Redirect server output to a log file instead of subprocess.PIPE.
   The pipes were never read, so any server that logs steadily (npm run
   dev, or http.server logging each request) fills the ~64KB pipe buffer
   and blocks mid-run, freezing the server and hanging the test.
   Reproduced: a stock http.server froze after ~1000 requests.

2. Start each server in its own process group and stop the whole group
   on cleanup. With shell=True, terminate() only killed the wrapper
   shell; the actual server survived and kept the port bound, so the
   next run would silently test a stale server. Reproduced with the
   documented "cd backend && python server.py" usage pattern.

3. Include the tail of the server log in the startup-failure error.
   Previously the server's real error (stuck in the unread pipe) was
   never shown, leaving "failed to start within 30s" as the only clue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013LKmYFWxnQJe4HaxBQTjyS
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