Repository navigation
Stop owned pytest processes when a TestPilot run is interrupted - #43
Conversation
Preserve KeyboardInterrupt while bounding POSIX child cleanup. Include focused real-process tests, original negative controls, independent generated-phase receiving and exact current-parent reviews for issue #35.
|
Additional native Linux receiving is now preserved at 66e5d7f4, based directly on unchanged offered head Receiver and exact source index · structured native result. On native Linux/Python 3.14, an independently authored actual-process receiver passed all three candidate groups: ordinary stdout/stderr/nonzero exit, same-group SIGINT cleanup, and the escaped-session retained-pipe boundary. The current original sandbox passes only the ordinary control. In the same-group negative, both processes remain active after the interrupted runner exits and write markers when a barrier is released afterward. The candidate has neither active process nor later marker. The detached child remains outside group cleanup and exits naturally when released. Four prior-output sentinels retain exact bytes, inode, mode and write timestamps; no receiver cleanup signals were needed. Candidate sandbox blob The full hosted gate remains failed. Existing job 113460074077 reports 397 passes and two authored escaped-child liveness failures on actual merge checkout The complete 62-file archive is 36,822 bytes, SHA256 |
Use ps -ww under pytest capture so owned escaped helpers remain observable. Preserve every liveness and timing assertion and the exact production cancellation handler. Retain the first hosted failure, native red/green evidence, diagnostic traces and complete root receiving proof.
|
Integrated and final receiving preserved by estate-18a24bf0c281. PR43 merged as 6c1c4973f6d88c3cc3d120c76a3b6e30f9008bbb; issue #35 is closed. Actual parents are Run 37833468085, attempt 1, job Final evidence is in receiving commit 4f49564ea24ba3d722b916ae2b72bf50d0e667a3, tree The original hosted failure remains in the merged ps-width-correction archive. Native diagnosis confirmed pytest's truncated ps observation, and the correction changed only the test helper to use |
Stop pytest when the caller cancels a run
Ctrl-C can return control to the caller while TestPilot's separately launched pytest process continues work. This change stops that owned POSIX process group when
KeyboardInterruptinterrupts the initial process communication, then propagates cancellation. Closes #35.Changes
testpilot/sandbox.py::_run: signal the owned process group, wait up to one second for its leader, close the output pipe and re-raise the interrupt. Cleanup errors do not replace the caller's cancellation.The source change is limited to this handler and its docstring. No parser, model, collector, output-writer, dependency or workflow change is included.
Preserved failure and native receiving
The original actual CLI witness on
f3b2135cad31852b599350564fe76dd160a6a522lets pytest write a work marker after its parent has exited on SIGINT. A barrier released only after parent exit establishes the ordering. The ordinary ScriptedModel control completes with two passing pytest cases and two accepted model entries. The first receiver'sledger.callsmetadata error is retained; v2 corrects that interface toledger.entries.Candidate receiving uses the exact current-parent composition at
7f44c4f134f4d56d37dd14c7c2d2aaa3c8c8749eplus frozen source649dc7d1fd02493af298876eea0697849404bba9. The original f3 execution is not relabeled as a newer-main run.The independent receiver interrupts generated-test verification after an actual existing-test pass and two accepted scripted replies. Its distinct handwritten fixture launches a finite worker inside pytest's process group. The original pytest and worker remain active and perform work after parent exit; the candidate leaves neither process active at parent exit and produces no later marker, without a receiver cleanup signal.
Four preexisting synthetic regular output sentinels retain exact bytes, inode, mode and write timestamps in both variants. They are preservation controls, not a claimed complete prior report. All 14 original and 16 candidate captured source files remain unchanged. The independent reviewer did not replay the author suite or ordinary control.
Native receiving used macOS arm64, Python 3.12.8 and pytest 9.1.1. Existing optional coverage was absent there; hosted full-suite qualification is separate.
Source composition and exact custody
The reviewed source branch is based on
362981dd84626fd55eda93584c2984cd9d0e5276, preserving PR41's completed-recheck HTML feature. The later review reproduces the entire prior recheck module by removing only its new writer block and imports. The renderer performs no work on import; the unchanged command boundary does not catchKeyboardInterrupt. This was a static composition review, with the earlier native results retaining their actual source attribution.Root verified all four publication packets by byte count, SHA-256, Git blob and mode. The initial source tree
83adbdd85b2733367ec04e0218b825cafcfd1bd7has 47 scoped paths: one parent file modified and 46 additions, with all 1,071 unrelated parent leaves preserved, for 1,118 total. All original controls, errors and evidence remain intact.The explicit-target composition at
eacb9907f51aeb9360da654c60cbbd7cf99ad877and later main513f17454af378ee042ccd29dc930ef332a48734passed separate source interaction reviews. Later changes validate positive finite timeouts and complete diff hunks; both frozen actual-CLI fixtures remain admitted with the same changed function and line. The loop, sandbox, package configuration and workflow remain exact, and added diff-error catches do not intercept cancellation. Earlier native results retain their original source bindings.Corrected process observation and hosted receiving
The corrected source head is
37985347ec7957902cc51223a0916b86ed5ef1f5, tree0760ae5048eaee2177493081def4c7735d0aad65. Its sole test change adds-wwto the process-list command, plus an explanatory comment. The complete text and AST inverse recover the original test; all liveness, timing and cleanup assertions remain intact. Production source is unchanged.The first hosted run passed 397 tests and 25 subtests but failed both new escaped-helper observations. On native Linux, the unchanged four-case group reproduced those two failures. Under pytest capture, ordinary
psreturned only 80 columns while the independently identified helper remained alive; the wide form retained the full fixture path. The corrected four cases pass without diagnostic instrumentation. The original failure, standalone negative diagnosis, process identities, raw observations and corrected logs are retained in the 147-member evidence archive and receiving notes.Hosted run 37833468085, job
113504469109, now passes 457 tests and 25 subtests on CPython 3.12.15 in 89.21 seconds. Root read the complete decoded log: 16,866 bytes, SHA-256ee9b7b0e5407aaf3d9f56d6275c15859a36cf370f080c9b8e630e15b6df4f8fc.The actual tested checkout is
fc1793cb048693e082e5abf18f577212ebe3792c, with parents current main513f17454af378ee042ccd29dc930ef332a48734and the corrected head. Root verified its complete tree29c33bd4dcd7d6d05d68e87b21530a7f3e69c3d8: all 52 contribution paths and 1,425 unrelated current-main leaves match exactly, for 1,477 leaves, with no conflict or omitted path.Boundaries and integration gate
The qualification covers POSIX SIGINT during initial communication. Escaped sessions remain outside group cleanup. The one-second leader wait excludes Python's brief interrupt-handling wait and scheduling delays. Earlier test effects and model calls are not rolled back, and SIGKILL does not run test teardown. Pre-Popen interruption, other signals and native Windows cancellation remain unqualified.
The unchanged Ubuntu/Python 3.12 full pytest workflow must pass for the actual PR composition before merge. This source contribution does not install or deploy a runtime.