Skip to content

Disable handle_basic behind the deferred-release-outlives-its-syscall issue, and run userdev_dma_fault on a binary with no census - #571

Merged
Japabu merged 4 commits into
mainfrom
wt/toyos-handlered
Sep 28, 2026
Merged

Japabu merged 4 commits into
mainfrom
wt/toyos-handlered

Conversation

@Japabu

@Japabu Japabu commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

handle_basic reds on the same mechanism already tracked for handle_kill_policy, handle_transfer and kill_while_blocked: the per-kind object census finding a live object behind after a release that has been queued but not yet run.

Decisions

  • handle_basic is disabled in src/redlist.rs behind that issue; a flaky test is disabled at once, never re-run. The evidence is a witness paragraph in the issue.
  • userdev_dma_fault carries test_rs_log_origin instead of test_rs_handle_basic. It ran handle_basic whole, census arm included, on the actuator kernel and required exit 0, so the same release-queue lag could still red the Fast tier there, reported as "the guest ran after the fault and failed" — an IOMMU fault-survival regression it is not. What the test needs from its binary is a process the machine spawns after the fault that exits 0. log_origin is the smallest built binary that runs standalone and exits 0 with nothing staged; the smaller ones panic, segfault, hold the boot for a host, or paint the screen. It is on RUST_SKIP, so no shared-boot declaration is needed; its RUST_SKIP comment now names userdev_dma_fault among its drivers.
  • handle_basic leaves DRIVEN_AND_SHARED: no machine test drives it any more, and suite_split reds on a stale entry.
  • The coverage gap is recorded in the issue: generation+1 reissue, superset-rights refusal, dup2's generations and a spent slot's retirement run in no gate while handle_basic is disabled, and the issue's exit brings them back by re-enabling it.

Gates (host, run here)

  • cargo test --lib: 384 passed, 0 failed, 1 ignored — exit 0
  • cargo test --test toyos-build -- --list: exit 0; prints [toyos] disabled: handle_basic — issues/kernel/deferred-release-outlives-its-syscall.md and lists userdev_dma_fault
  • cargo run -- --known-red handle_basic: handle_basic: YES, disabled — it does not run. — exit 0
  • cargo run -- --build-only: exit 0

Guest arms (orchestrator's measurements, at 6c3af992)

  • Green: userdev_dma_fault EXIT=0, passing with test_rs_log_origin; suite_split EXIT=0 (no guest; it reads DRIVEN_AND_SHARED against the harness).
  • Negative control: a kernel that halts for a fault on a process-driven stream — drain in kernel/src/arch/x86_64/vtd/fault.rs counting every fault rather than only owner.is_none() ones, so iommu-userdev-foreign-dma's fault takes the halt_all_cpus path. The mutated tree builds (cargo run -- --build-only --kernel-param iommu-userdev-foreign-dma, exit 0); the patch is not committed. Run against it, userdev_dma_fault EXIT=1: "the guest stopped answering after the fault: QEMU disconnected", after the fault itself was delivered (DMA FAULT owner=slot0) — the half the carried binary answers.
  • Fast tier: 396 passed, 1 failed — the failure is log_ring_keeps_the_owners_slots, already disabled on main.
  • Independent oracle: QEMU's intel-iommu fault recording, which is what foreign_fault already reads the fault from.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j

… issue

The census instrument reds it the same way it reds handle_kill_policy,
handle_transfer and kill_while_blocked: one extra live PipeWrite behind
after handle churn, the last round's drop(write) still in the release
queue at the second reading. A flaky test is disabled at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
@Japabu
Japabu marked this pull request as ready for review September 28, 2026 08:06
@Japabu

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #571 at d6e1a0f7. CI run 36395426890 has host=success at d6e1a0f7a4c0. I re-ran the host gates in /Users/jan/Dev/jan/toyos-handlered:

  • cargo test --lib: EXIT=0, 384 passed, 1 ignored.
  • cargo test --test toyos-build -- --list: EXIT=0. It prints [toyos] disabled: handle_basic — issues/kernel/deferred-release-outlives-its-syscall.md and still lists handle_basic and userdev_dma_fault.
  • cargo run -- --known-red handle_basic: EXIT=0, YES, disabled.

Net: +11/−0. One line is redlist data and ten are issue prose.

BLOCKER

  • tests/common/iommu.rs:2059-2085, tests/toyos.rs:1546,1668 — the assertion this row disables still runs in the Fast tier, under the name userdev_dma_fault. That test is Fast and has no redlist row. It carries test_rs_handle_basic through carried_by/qemu::carrying, which read the unfiltered rust_bins: keep filters test names, not binaries. It runs the whole binary, census arm included (handle_basic.rs:301-311), and requires exit 0. Its boot is the actuator kernel: iommu-userdev-foreign-dma lives in kernel/src/actuator.rs:487, and a_spent_slot_retires… asserts that SYS_DEBUG answers. So the same deferred-release lag can still red the PR gate. When it does, the report will read "the guest ran after the fault and failed: exit Some(101)", which presents a release-queue lag as an IOMMU fault-survival regression. The flaky assertion is not disabled; it has moved to a test whose red misleads. The orchestrator has two options, and either one must land with this row:
    • disable userdev_dma_fault behind the same issue; or
    • point userdev_dma_fault (toyos.rs:1668, iommu.rs:2061) at a binary that has no census arm, and record the coverage gap in the NOTE below.

NOTE

  • Attribution holds, but it rests on reading the code, not on a measurement. Both witnesses have the same shape: PipeWrite +1 and every other kind equal.

    • The Fast log is 564r2-fast.log:722, 5→6 on a baseline of PipeRead 6, PipeWrite 5.
    • The CI log is job 99138099030, log line 388, 1→2 on PipeRead 2, PipeWrite 1, followed by ALONE handle_basic: GREEN.
    • round() drops write last (handle_basic.rs:326-327). PipeWrite is a deferred sealed row (kernel/src/object/mod.rs:250). The census counter falls only in ObjectCore's drop, and that drop happens after the queue's Arc goes. So the last syscall's enqueue, taken by another CPU's drain, reads exactly like this.
    • Neither log has a third reading that settles back to baseline. Because Census::now() is machine-wide, a daemon holding one new write end while dropping a read end is not excluded by measurement. It is only less parsimonious.
  • Coverage that has no other running gate once userdev_dma_fault stops carrying this binary:

    • (1) a closed slot is reissued at generation+1;
    • (2) the refusal of a superset of rights;
    • (4) dup2 answers generation 0, then 1, and a live replace keeps its generation;
    • (5) retirement at MAX_GENERATION - 1 and a table exactly one slot smaller.

    kernel/src/object/handle.rs has no host test. toyos-abi/src/handle.rs's tests pin only the encoding. abuse_handle_table checks the cap and not generations. The only other caller of SLOT_TO_LAST_GENERATION is handle_kill_policy.rs:496, and that test is disabled. Still covered by running tests: DUP refusal (device_claim_lifetime.rs:70-88) and narrowed rights enforced on use (process_stats.rs:271-276). This gap belongs to the issue's owner.

  • The issue's exit covers three rows (handle_basic, handle_transfer, kill_while_blocked). Under issues/README.md §Closing, deleting the file deletes those rows. handle_kill_policy comes back through its own issue, whose exit condition names this issue's fix. Nothing is stranded.

  • src/redlist.rs:38 — the row's shape, order and form match its siblings. check_redlist refuses a misspelled name or a non-expected-red issue before any boot.

REMOVE

  • issues/kernel/deferred-release-outlives-its-syscall.md:94-95 — "PR tests: the measured schedule — Fast is every PR, then Nightly, then Weekly; 15 never-caught tests and the kernel code only they armed deleted #564 does not change the tests that run with it (its reviewer checked this)". This is provenance narration and not load-bearing.
  • issues/kernel/deferred-release-outlives-its-syscall.md:98-99 — "Its redlist row cites this paragraph." This is false: src/redlist.rs:38 names the file, not a paragraph.
  • issues/kernel/deferred-release-outlives-its-syscall.md:91 — "fifth". This is an ordinal count in a file that already has two "fourth witness" headings (:81, :256).
  • PR body — "(no new prose beyond the evidence lines)". This describes the change itself and is not load-bearing.

SEND BACK

… runs in Fast

userdev_dma_fault carried test_rs_handle_basic and required exit 0 after
the staged DMA fault. With handle_basic disabled behind
deferred-release-outlives-its-syscall, its census arm still ran there, on
the actuator kernel, and a release-queue lag would have read as "the guest
ran after the fault and failed" - an IOMMU fault-survival regression it is
not.

What userdev_dma_fault needs from its binary is a process that the machine
spawns after the fault and that exits 0. log_origin is the smallest built
binary that runs standalone and exits 0 with nothing staged (661104 bytes;
the smaller ones panic, segfault, hold the boot for a host, or paint the
screen), and it is on RUST_SKIP, so no shared-boot declaration is needed.
handle_basic is no longer driven by any machine test, so its
DRIVEN_AND_SHARED entry goes, as suite_split requires.

The issue records the assertions handle_basic alone held, which now run in
no gate, and that its exit brings them back. The review's REMOVEs are taken.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
@Japabu Japabu changed the title Disable handle_basic behind the deferred-release-outlives-its-syscall issue Disable handle_basic behind the deferred-release-outlives-its-syscall issue, and run userdev_dma_fault on a binary with no census Sep 28, 2026
@Japabu

Japabu commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Review round 2 of #571 at 6c3af992. CI: run 36398544950, host = COMPLETED/SUCCESS at 6c3af992. Guest runs are the orchestrator's, logs 571r2-*: userdev_dma_fault PASS; suite_split PASS; arm red-arm-halt-on-process-fault.patch → userdev_dma_fault FAIL, "the guest stopped answering after the fault: QEMU disconnected" (arm log :37), after DMA FAULT owner=slot0 (:254); Fast 396 passed, 1 failed, and the failure is log_ring_keeps_the_owners_slots (fast log :577), which main disables.

Net origin/main...HEAD: +23/−14. Production 0. Tests and harness +10/−14 (iommu.rs 6/6, toyos.rs 3/8, redlist.rs 1/0). Issue prose +13.

Earlier findings

  • BLOCKER (handle_basic's census still ran in Fast through userdev_dma_fault): CLOSED. git grep handle_basic at HEAD: the only harness references are the redlist row and ACTUATOR_TESTS, and no CARRIES or rust_bins filter names it. userdev_dma_fault carries test_rs_log_origin (toyos.rs:1663, iommu.rs:2061,2085) and passes at this head. The arm shows the survival half still reds on a kernel that halts for a process-owned fault.
  • NOTE (coverage gap belongs to the issue's owner): CLOSED. The gap is recorded at issues/kernel/deferred-release-outlives-its-syscall.md:98-102.
    • I checked it against the tree. SLOT_TO_LAST_GENERATION is driven only by handle_basic and the disabled handle_kill_policy. Generation-checking dup2 exists only in handle_basic. device_claim_lifetime covers only property 3, which the sentence rightly leaves out.
    • Under issues/README.md §Closing the redlist row goes with the file, so the exit does re-enable handle_basic.
  • REMOVE ":94-95 reviewer checked this": CLOSED, deleted.
  • REMOVE ":98-99 Its redlist row cites this paragraph": CLOSED, deleted. The same sentence at :88-89 is main's and belongs to the handle_transfer paragraph.
  • REMOVE ":91 fifth": CLOSED. The word was deleted and nothing was reworded around it.
  • REMOVE "PR body (no new prose beyond the evidence lines)": CLOSED, absent from the body.

BLOCKER

None.

NOTE

  • Branch: the merge base is 51fe14c1 and it predates Disable log_ring_keeps_the_owners_slots behind its filed defect #569 and The orchestrator edits nothing: every change goes through an agent and a review round #570. origin/main (a7cd3276) is not an ancestor. Merge origin/main. git merge-tree finds no conflict. This clears the one Fast red, log_ring_keeps_the_owners_slots.
  • tests/common/iommu.rs:2085 — lost, and not recorded: after the fault, userdev_dma_fault no longer makes and closes an object of every kind with a per-kind census on the actuator kernel. That was the old comment's "a kernel limping after the fault fails it". The issue's exit restores handle_basic's own run but not this post-fault breadth. It is accepted: the test's documented claim is survival (scheduler, spawn, the runner's stdout pipe), log_origin exercises all three, and the arm proves that half discriminates.
  • PR body — the guest arms are stated with no command, exit code or log. Carry the orchestrator's 571r2 results: userdev_dma_fault EXIT=0, suite_split EXIT=0, arm EXIT=1 with its reason line, Fast 396/1 with the one red named.

REMOVE

  • tests/toyos.rs:197-198 — "log_program_line, log_stream and userdev_dma_fault run it." — Prose was rewritten instead of deleted. It restates what CARRIES answers (:1663, :1732, :1740, :1741) and is already wrong, because it omits log_stream_e1000e.
  • PR body, "Unsure" — The arm log answers it: the red arrives as result.error.
  • PR body — "(one println!, 661104 bytes built) is the smallest built binary … or paint the screen". The criterion is that it asserts nothing, not its size, so this sentence is not load-bearing.
  • PR body, "Independent oracle" — "the kernel's own stated policy at fault.rs's halt site". The author's own comment is not independent.

LAND AFTER NAMED CHANGES

Japabu and others added 2 commits September 28, 2026 12:19
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
…it, and it omits log_stream_e1000e

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
@Japabu
Japabu enabled auto-merge September 28, 2026 10:23
@Japabu
Japabu added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit af817e5 Sep 28, 2026
1 check passed
@Japabu
Japabu deleted the wt/toyos-handlered branch September 28, 2026 10:47
Japabu added a commit that referenced this pull request Sep 28, 2026
#571's removal of `handle_basic` from `DRIVEN_AND_SHARED` merges on its
own, since the list is back in `tests/toyos.rs` byte for byte as main had
it.

`kernel-loom/tests/i8042_tally.rs` takes main's side whole: #567 moved
every loom model onto a fork that races a store against every thread's
last load, and asserts that the tally models reach their named cases, so
this branch's reordering and its `explored` guard, which worked around
the gap, go. The branch's issue about that gap
(`loom-never-moves-a-store-before-a-load-another-thread-made-first`)
closes with it, since #567 meets its exit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
Japabu added a commit that referenced this pull request Sep 28, 2026
Takes #567, #570 and #571 at af817e5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
Japabu added a commit that referenced this pull request Sep 28, 2026
The orchestrator's nightly at 925e1a6 red it on netd's
"this NIC's claim refused an interrupt read: Io" from Card::begin_pass, 22 ms
after the staged DMA fault. That panic is netd's designed answer to a claim
the kernel refuses after a fault, and the test forbids it, so the test passes
only while netd has not reached its loop. Neither this branch, which changes
neither netd nor logd and captures fewer lines for this test than main, nor
#571 caused it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
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