generated from erix/meta
[BUG] Socket fixture startup hides worker failures and skips partial cleanup #42
Labels
No labels
bug
ci
docs
duplicate
enhancement
help wanted
invalid
performance
phase-6
question
refactor
security
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
erix/integration#42
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Summary
The host
FakeGuestfixture does not unwind partial startup and can replace an earlier worker failure with a generic readiness timeout. Callers start the fixture before entering their cleanup blocks, so a failed start skips theirjoin()calls. This affects fixture diagnostics and thread ownership, independently of the serial write-timeout defect in #41.Reproduction
The retained local validation invoked
python3 -B -Werror tests/interactive_shell_transport_test.pyon a frozen test-only candidate based on Integration9f004461b284493b7b53d386c8727435b02abe0f. Four serial cases reportedAssertionError: fake COM1 socket did not become ready; the other three cases passed. The file ran seven tests in 5.438 seconds and exited 1.No new reproduction was run for this report. The original published startup implementation has identical control flow to the observed candidate, now published at
fe8c8103719af9c127dd769f4427d2a346e1ffd9. A longer temporary directory is a source-supported explanation for a socket setup failure, but the actual worker exception was not retained, so that explanation is not established.Expected and actual behavior
A startup failure should preserve the first worker or thread-start error, stop and account for every successfully started worker, and retain cleanup failures separately. A readiness timeout should be reported when no earlier startup failure is available.
Currently
guarded()stores worker exceptions and sets the stop event, whilestart()waits for readiness and raises a new generic assertion without consulting those exceptions or unwinding owned workers. Each of the three transport call sites callsstart()before itstry/finally. The observed failures therefore bypassed the caller'sjoin()path. The retained evidence does not establish a surviving thread or an unclosed socket; the enclosing command owner reported no cleanup failure.Environment and identity
9f004461b284493b7b53d386c8727435b02abe0f.tests/interactive_shell_transport_test.pySHA-256:7828ead8ae37e1ae231fa81d3f4715968d96eb09e97eca0cd8564f5abdbab811.8b20cb4bc36fcdc4e7a00fbf8822c2cec176fe77a6b9ff08b3ccc03e1a1e1c8c.Evidence and prior checks
The four failing cases were
test_com1_second_command_stall_is_not_masked,test_com1_three_lines_and_three_new_prompts,test_factory_failure_still_quits_private_vm, andtest_sequence_factory_reuses_qmp_without_physical_events_on_com1. Each retained traceback stops at the readiness assertion; none exposes the worker's original error.Original source anchors are
guarded()at lines 137–142,start()at 144–157, and starts before cleanup at 173, 200 and 216. The candidate preserves that startup control flow. The nine preceding socket-I/O controls passed; their scope is established connections and write/stop behavior, not partial-start unwinding.Future regression coverage should exercise an explicit worker failure before readiness, QMP startup failure after serial readiness, a later
Thread.start()failure after one successful start, and readiness timeout without a recorded earlier failure. Each case must verify all actually started workers are accounted for and cleanup cannot replace the primary error. A successful startup control must remain. The existing five-second listeneraccept()wait also needs explicit retirement ownership; merely movingstart()inside callerfinallydoes not make a two-second join sufficient.The signed correction is
37299e719d7662698593c6d3be24752309bed7ec. Startup is single-use and reserves every attempted worker before calling Thread.start. Worker, launch and initial-output failures use one ordered error record; every startup exception requests stop and attempts all worker joins before preserving the primary failure. The powerbox/editor listeners use the same stoppable accept helper. A separate startup commit gate holds early clients until initial output and the final failure check complete. One original absolute five- or ten-second allowance covers both gate waiting and acceptance. Existing connected QMP protocol deadlines remain separate; incomplete cleanup is still an error.All 122 cases across 15 affected host suites pass, including 20 startup controls. Actual early connections, partial launches, failed initial output, listener retirement and stop are covered. The first candidate's runtime-errors failure remains retained: an independent runner may connect as soon as the path appears, before the completion hook. The corrected gate passes both runtime-errors transports and the complete affected suite. All 116 Markdown files, 71 workflow shell bodies, source contracts and whitespace checks pass. The new checkpoint's CI remains pending; no production observer limit or command assertion changed.
Tracking
Related but distinct: Integration #41, which concerns established fake-guest serial writes inheriting the receive polling timeout. This report concerns startup failure attribution and partial-start cleanup. No runtime defect, exploit, shared root cause or guest acceptance claim is made.
erikinkinen referenced this issue2026-09-13 04:43:04 +02:00