Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions issues/kernel/deferred-release-outlives-its-syscall.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ recorded mechanism through the census instrument on the hosted shard — the
first sighting of this class off the dev host. Its redlist row cites this
paragraph.

**A witness, PR #564 at `4919fbd7`.** `handle_basic` red at
`tests/toyos-rust-tests/src/bin/handle_basic.rs:305` — sixteen more rounds of
handle churn left one extra live `PipeWrite` behind (`[("PipeWrite", 5, 6)]`),
`PipeRead` unchanged. CI run 33266767478, job 99138099030 reds the same
assertion on `wt/toyos-wv-fs` at `b10c4daf`, green when run alone. `PipeWrite`
+1 with `PipeRead` unchanged is the last round's `drop(write)` still in the
release queue at the second census reading: this issue's defect.
While `handle_basic` is disabled, four of its assertions run in no gate at all —
a closed slot reissued at generation+1, a superset of rights refused, `dup2`
answering generation 0, then 1, and keeping it across a live replace, and a
spent slot retiring with the table exactly one slot smaller — so this issue's
exit brings them back by re-enabling it.

## A syscall answering the wrong word, 2026-08-20

**The three witnesses above are quantities that settle. This one is not.**
Expand Down
1 change: 1 addition & 0 deletions src/redlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub const DISABLED: &[Disabled] = &[
},
Disabled { test: "desktop_window_child", issue: "issues/kernel/desktop-window-child-freeze.md" },
Disabled { test: "doom_sound_flood", issue: "issues/audio/doom-sound-flood-played-full-scale-once.md" },
Disabled { test: "handle_basic", issue: "issues/kernel/deferred-release-outlives-its-syscall.md" },
Disabled {
test: "handle_kill_policy",
issue: "issues/kernel/handle-kill-policy-census-grew-one-sharedmem-on-two-nightlies.md",
Expand Down
12 changes: 6 additions & 6 deletions tests/common/iommu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2053,16 +2053,16 @@ pub fn userdev_dma_fault(
) -> Result<(), String> {
let _ = c_bins;
// One guest binary, for the half of this test the fault line cannot say:
// that the machine still schedules, spawns, and answers. `handle_basic`
// makes and closes an object of every kind and counts the census, so a
// kernel limping after the fault fails it rather than passing vacuously.
// that the machine still schedules, spawns, and answers. `log_origin` says
// one line and exits, and asserts nothing else: a verdict that rides a
// deferred release would red here as a fault it is not.
let bins: Vec<(String, Vec<u8>)> = rust_bins
.iter()
.filter(|(name, _)| name == "handle_basic")
.filter(|(name, _)| name == "log_origin")
.cloned()
.collect();
if bins.is_empty() {
return Err("handle_basic was not built".to_string());
return Err("log_origin was not built".to_string());
}
let mut qemu = foreign_fault(test_config, &[], &bins, &USERDEV_FOREIGN)?;
let log = Serial::named("boot console", qemu.boot_log().to_string());
Expand All @@ -2082,7 +2082,7 @@ pub fn userdev_dma_fault(
// And the machine is running. This is the assertion the whole stage is
// for: a guest that answers here is one whose scheduler, spawn path and
// IPC all survived a device being refused mid-flight.
let result = qemu.run_test("test_rs_handle_basic", Duration::from_secs(60));
let result = qemu.run_test("test_rs_log_origin", Duration::from_secs(60));
if let Some(err) = &result.error {
return Err(format!(
"the guest stopped answering after the fault: {err}\n{}\n{}",
Expand Down
10 changes: 2 additions & 8 deletions tests/toyos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,7 @@ const RUST_SKIP: &[&str] = &[
// `log_program_forgery` runs it.
"log_forger",
// Its verdict is where its one line went — `/log`, the served log and the
// console — which only a boot of its own reads back. `log_program_line`
// and `log_stream` run it.
// console — which only a boot of its own reads back.
"log_origin",
// Its verdict is where its line lands among the kernel's records, which
// every other binary's records would crowd. `log_program_line_after_its_records`
Expand Down Expand Up @@ -491,11 +490,6 @@ const DRIVEN_AND_SHARED: &[&str] = &[
// The log-stream arms drive it for the kernel's `exit:` record about it,
// not for anything it does: it is the cheapest process this tree starts.
"empty_dir_stat",
// Its shared run is a whole handle-lifecycle gate with its own census;
// `userdev_dma_fault` drives the same binary for a different reason
// entirely — as the proof the machine still schedules and spawns after a
// device was refused at the unit — and stages nothing for it.
"handle_basic",
"hierarchy_paths",
"null_sink_client_exits",
"nvme_home_roundtrip",
Expand Down Expand Up @@ -1665,7 +1659,7 @@ const CARRIES: &[(&str, &[&str])] = &[
("input_claim_absent", &["test_rs_input_absent"]),
("gpu_set_resolution", &["test_rs_gpu_set_resolution"]),
("iommu_gpu_scanout_swap", &["test_rs_gpu_scanout_swap"]),
("userdev_dma_fault", &["test_rs_handle_basic"]),
("userdev_dma_fault", &["test_rs_log_origin"]),
("userdev_residue_is_its_own", &["test_rs_userdev_residue"]),
("blockd_serves_partitions", &["test_rs_blockd_io"]),
("blockd_survives_its_death", &["test_rs_blockd_io"]),
Expand Down
Loading