Skip to content

test(harness): bounded join gate, reap seam, launcher-bound selftests - #2683

Merged
chaliy merged 11 commits into
mainfrom
codex/syntax-diagnostic-budget
Oct 11, 2026
Merged

chaliy merged 11 commits into
mainfrom
codex/syntax-diagnostic-budget

Conversation

@chaliy

@chaliy chaliy commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

What changed

Test-only, one file: threat_model_tests.rs. Closes the lifecycle review on #2682 without touching #2681 distinct run_bounded_probe helper:

  • Bounded join gate: readers join only after all channel receipts (a receipt proves its thread finished every blocking call; sending is the last act before return). Missing receipts skip the join and fail incomplete; panicking readers fail visibly via join error. std offers no timed join; the gate plus elapsed-total assertions are the documented termination proof.
  • Reap extracted into a poll seam (reap_with_grace) with deterministic verdict unit tests: immediate, delayed, never-exits (bounded 50ms), and poll-error cases.
  • Timeout/overflow selftests run under the shared fail-closed launcher (new run_raw_bounded) so the effective stack=4096/cpu=10 bounds are applied and read back, with elapsed-total bounds (2s+2s+5s budget).
  • Existing bounded_helper_flags_retained_pipes reused and strengthened: elapsed proof (returns without waiting for the 30s sleeper), read_error distinction, outer-deadline documentation.

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

  • Test-only change. No production code touched.

Checklist

  • Tests added or updated
  • Backward compatibility considered (internal test harness)

chaliy added 11 commits October 10, 2026 21:58
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.
All five branch commits already reached main via squash merges (#2675, #2677); conflicting files take main's reviewed state.
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.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

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

@chaliy

chaliy commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

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.

@chaliy
chaliy merged commit f6cefae into main Oct 11, 2026
33 checks passed
@chaliy
chaliy deleted the codex/syntax-diagnostic-budget branch October 11, 2026 10:31
chaliy added a commit that referenced this pull request Oct 11, 2026
…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.
chaliy added a commit that referenced this pull request Oct 11, 2026
…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)
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