Commit 840c0db
committed
Rewrite TestChildProcessCleanup with socket-based deterministic liveness probe
Replaces the file-growth-polling approach with a fundamentally different
design: each subprocess in the tree connects a TCP socket back to a listener
owned by the test. Liveness and death are then detected via blocking I/O
operations that unblock on kernel-level events — zero sleeps, zero polling:
1. await listener.accept() blocks until the subprocess connects
(proves it started).
2. After _terminate_process_tree(), await stream.receive(1) raises
EndOfStream because the kernel closes all file descriptors of a
terminated process. This is direct, OS-guaranteed proof that the
child is dead.
Compared to the original file-watching approach:
- No tempfiles, no file I/O, no path escaping
- No fixed sleep() durations (the root cause of flakiness)
- No polling loops
- Failure modes are clear: accept times out = child never started;
receive times out = child survived termination (actual bug)
Also fixes the process leak on assertion failure by adding proc cleanup
to each finally block (guarded by proc=None after successful in-test
termination to avoid noisy double-terminate).
Result: 3 tests drop from ~7.1s to ~0.5s, 30/30 pass under 4-worker
parallel load. Removes 80 net lines and the tempfile/path-escape deps.
Closes #1775
Github-Issue: #17751 parent 68c6e0b commit 840c0db
1 file changed
+155
-227
lines changed
0 commit comments