Signals over IPC, one-shot timers, and the service harness (M17.4)
Signals are statements delivered as coalescing notifications to the endpoint a process nominates with signal_bind — never a hijacked stack, never a question (liveness is the zero-length ping the harness answers). process_signal is supervisor-or-self gated, like kill; unbound targets accumulate a pending mask delivered on bind. timer_bind is the missing timed wait: a one-shot deadline landing in the same replyWait as everything else — what stop(), hello deadlines, and restart backoff are built from. runtime.service.run folds requests, signals, and notifications into callbacks; the VFS conversion deletes its hand-rolled loop and gains the whole lifecycle contract. The signals scenario drives ping, reload, terminate->exited, the timer, and the deaf-child deadline->killed path from ring 3. docs/process-lifecycle.md increments 1-4 are now as-built.
This commit is contained in:
@@ -136,6 +136,8 @@ pub fn run(case: []const u8, boot_information: *const BootInformation) void {
|
||||
claimReleaseTest(boot_information);
|
||||
} else if (eql(case, "vfs-client-death")) {
|
||||
vfsClientDeathTest(boot_information);
|
||||
} else if (eql(case, "signals")) {
|
||||
signalsTest(boot_information);
|
||||
} else if (eql(case, "initial-ramdisk")) {
|
||||
initialRamdiskTest(boot_information);
|
||||
} else if (eql(case, "vfs")) {
|
||||
@@ -1605,6 +1607,53 @@ fn vfsClientDeathTest(boot_information: *const BootInformation) void {
|
||||
result();
|
||||
}
|
||||
|
||||
/// M17.4 from ring 3: process-test's signal-run role drives the whole lifecycle
|
||||
/// surface — the zero-length ping (answered by the harness), signals as
|
||||
/// statements (reload logged, terminate = clean exit), the one-shot timer, and
|
||||
/// both endings of the stop sequence (polite -> exited, deaf -> killed at the
|
||||
/// deadline). Its "process-test: signals ok" is the pass marker.
|
||||
fn signalsTest(boot_information: *const BootInformation) void {
|
||||
log("DANOS-TEST-BEGIN: signals\n", .{});
|
||||
if (boot_information.initial_ramdisk_len == 0) {
|
||||
check("bootloader handed over an initial_ramdisk", false);
|
||||
result();
|
||||
return;
|
||||
}
|
||||
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
|
||||
const rd = initial_ramdisk.Reader.init(image) orelse {
|
||||
check("initial_ramdisk image is valid", false);
|
||||
result();
|
||||
return;
|
||||
};
|
||||
|
||||
process.setInitialRamdisk(image); // the parent system_spawns its children by name
|
||||
process.write_count = 0;
|
||||
var runner: u32 = 0;
|
||||
var i: u32 = 0;
|
||||
while (i < rd.count) : (i += 1) {
|
||||
const item = rd.entry(i) orelse continue;
|
||||
if (!eql(item.name, "process-test")) continue;
|
||||
runner = process.spawnProcessSupervised(item.blob, 4, &.{ "process-test", "signal-run" }, scheduler.currentId(), null) catch 0;
|
||||
break;
|
||||
}
|
||||
check("signal-run parent spawned", runner != 0);
|
||||
|
||||
const pass_marker = "process-test: signals ok";
|
||||
const fail_marker = "process-test: FAIL";
|
||||
scheduler.setPriority(1);
|
||||
const deadline = architecture.millis() + 15000;
|
||||
var saw_pass = false;
|
||||
var saw_fail = false;
|
||||
while (architecture.millis() < deadline and !saw_pass and !saw_fail) {
|
||||
if (process.write_len >= pass_marker.len and eql(process.write_buffer[0..pass_marker.len], pass_marker)) saw_pass = true;
|
||||
if (process.write_len >= fail_marker.len and eql(process.write_buffer[0..fail_marker.len], fail_marker)) saw_fail = true;
|
||||
scheduler.yield();
|
||||
}
|
||||
scheduler.setPriority(4);
|
||||
check("the signal-run parent reported ok", saw_pass and !saw_fail);
|
||||
result();
|
||||
}
|
||||
|
||||
/// The whole user-side surface at once: spawn process-test's supervisor role,
|
||||
/// which — entirely from ring 3 — creates an exit endpoint, spawns its two
|
||||
/// children supervised, sees them in process_enumerate, kills them (one blocked,
|
||||
|
||||
Reference in New Issue
Block a user