Repository navigation
test(harness): bounded join gate, reap seam, launcher-bound selftests - #2683
Conversation
macOS bash 3.2 reports -c input as line 0, modern GNU bash as line 1. Compare diagnostic shape with line number normalized.
…gression A long -c ARG0 stamped on every report line could evict the structural payload out of the 1 KiB diagnostic budget. Truncate the shell name to 64 chars first so 'syntax error ...' always survives; renumber the threat entry to TM-DOS-136 (main already owns 135 via #2674); add a bounded-child regression exercising the exact finding shape (multiline token x long ARG0) at two scales.
The 64-char cut mangled long script paths (breaking the oracle's path
replacement and hiding which script failed). Widen to 256 chars with a
16-char tail: realistic paths print verbatim with attribution suffixes
(': eval') intact, while a kilobyte-scale ARG0 still cannot evict the
structural payload out of the 1 KiB total. The total stays the enforced
bound.
The scaled multiline-token x long-ARG0 regression now asserts the whole harness contract at both scales (200/2000 lines x 8 KiB ARG0): no watchdog timeout, raw child exit 2, no output-cap overshoot, finished reader threads, and effective stack=4096/cpu=10 caps read back from the launcher. Shape and 1 KiB assertions unchanged.
run_command_bounded cleanup per lifecycle review: truncate retention before extending (retention never passes the 8192 cap); retry Interrupted, fail closed with partial bytes on real reader errors (new read_error field, never relabeled as EOF); exact-cap EOF is not excess; reap inside a finite 5s grace, never an unbounded wait; timed_out retained as recorded; drain 2s + reap 5s graces documented against the execution deadline. Consumer regression gains !read_error and the corrected 8192-byte cap text. Bounded selftests: exact-cap, cap+1, Interrupted/error scripted pipes, timeout kill+reap, overflow flag.
Per lifecycle review on #2682: join readers only after all channel receipts (receipt proves all blocking work done; missing receipts skip the join and fail incomplete), with panicking readers failing visibly; reap extracted into a poll seam with deterministic verdict unit tests; timeout/overflow selftests run under the fail-closed launcher with stack/cpu readback and elapsed-total bounds; retained-pipe case gains elapsed proof and read_error distinction. Reuses existing bounded_helper_flags_retained_pipes; does not touch #2681's distinct probe helper.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | c98b30d | Commit Preview URL Branch Preview URL |
Oct 11 2026, 10:03 AM |
|
Lifecycle follow-up on exact c98b30d (not a request to duplicate the existing retained-pipe test). The shared CPU/stack launcher and bounded reap poll seam are useful improvements. However the join block still performs unconditional reader.join() after receiving messages. A sender can be descheduled after tx.send and before return; receiving its final message is not the std::thread termination contract. Please poll JoinHandle::is_finished within a finite shared completion grace, join only finished handles, and return incomplete for unfinished handles. Add a deterministic paused-after-send completion seam/test under an outer watchdog rather than claiming a demonstrated current hang. Preserve honest total execution/drain/reap/completion bounds and cap-before-copy/read-error fail-closed behavior. The current reap seam tests exercise only the helper's return value, and the read-error tests exercise only drain_capped. Please assert propagation through the actual parent verdict for unavailable reap/poll error/read error with focused safe injection seams; a helper-only unit test is not proof of parent error handling. bounded_helper_flags_retained_pipes already directly exercises run_command_bounded; retain and strengthen it, do not add a duplicate. It still launches bare bash rather than the effective CPU/stack launcher, and returns while sleep30 and reader threads remain. A finite sleep is useful but does not prove cleanup. Apply/read back effective child bounds and give the fixture an outer controlled finite cleanup path with receipts for its descendant and readers. Keep the truthful incomplete verdict; do not weaken flags or claim process-tree reaping is portable. The overflow selftest lacks an elapsed-total assertion despite the PR body's claim. Preserve expected producer exits versus assertion-harness success, existing scaled error+partial ARGV assertions, unrelated benchmark files/stashes and all prior history. Read full issue comments as well as formal/inline reviews before merging. Current pending CI is unknown, not green; 220 tests with the misconfig skip is partial evidence, not an unchanged Linux full-gate waiver. |
…tests Per completion review on #2683: join readers only while is_finished inside the shared completion grace (a receipt is not the termination contract); deterministic paused-after-send proof with release/cleanup watchdog; poll/read/reap faults injected through the real parent lifecycle with distinct fail-closed verdicts (no panicking expect on child poll); timeout/overflow selftests under the fail-closed launcher with cap readback and elapsed bounds; existing retained-pipe fixture reused and strengthened. Untouched: #2681 distinct probe helper.
…tests (#2684) ## What changed Test-only, one file: threat_model_tests.rs. Closes the completion review on #2683 without touching #2681 distinct run_bounded_probe helper: - Bounded join completion gate: readers join only while is_finished inside the shared completion grace (JOIN_GRACE 5s; full budget is execution limit + drain 2s + reap 5s + completion 5s). A channel receipt is not the termination contract since scheduling can pause the sender after send. Unfinished handles stay detached and fail incomplete; panicking readers fail visibly. No reproduced production hang is claimed. - Deterministic paused-after-send proof with explicit release/cleanup path and watchdog: a sender blocked on release reads unfinished by construction, releases cleanly, and joins inside the bound. - Poll/read/reap faults injected through the real parent lifecycle (LifecycleFaults seam): poll failure fails closed with a verdict distinct from timeout (incomplete, reap-recovered exit, no timeout); injected read failure propagates read_error with partial capture; unavailable reap yields exitless incomplete. The panicking child.try_wait expect is gone. - Timeout/overflow selftests run under the shared fail-closed launcher with stack/cpu readback and elapsed-total bounds. - Existing bounded_helper_flags_retained_pipes reused and strengthened (elapsed proof, read_error distinction, outer-deadline documentation). ## Before / After Before: unconditional join after receipts; reap untestable without OS fakery; child poll panicked; selftests bypassed the launcher. After: threat_model 222 passed (only pre-existing macOS nesting abort skipped, identical on unmodified code); error 14, partial_parse 11 green; fmt plus clippy -D warnings clean. ## Risk - Test-only change. No production code touched. ## Checklist - [x] Tests added or updated - [x] Backward compatibility considered (internal test harness)
What changed
Test-only, one file: threat_model_tests.rs. Closes the lifecycle review on #2682 without touching #2681 distinct run_bounded_probe helper:
Before / After
Before: unconditional join past the grace; reap untestable without OS fakery; selftests bypassed the launcher; no elapsed proofs.
After: threat_model 220 passed (only pre-existing macOS nesting abort skipped, identical on unmodified code); error 14, partial_parse 11 green; fmt plus clippy -D warnings clean.
Risk
Checklist