From 6452c540a207a120de9b6cc7a9e05dad55a382b7 Mon Sep 17 00:00:00 2001 From: rajames Date: Mon, 26 Oct 2026 13:04:06 -0400 Subject: [PATCH] fix(v4): the identity gate's final review, items 1-4 From the fresh whole-branch review of the identity gate (With fixes; no Critical, four Important): 1. A drive pulled while a line ran: the drives are looked at before every prompt (sk_v4_identity_check_now), so no prompt is shown once she is gone and what was typed after the pull does not run as Zuse. 2. Pulled while a line WAITS: the wait is ended at logout, by an empty line, and not carried into her next session (Captain Bob, 2026-10-26: "end the waiting line at logout"); re-attaching brings the prompt back. 3. EMERGENCY_CONSOLE_ENABLED: v4 honours it as v3 does -- a bring-up build has a prompt with no drive (boards/BRINGUP.md A2). 4. Keys typed at a headless machine are read and dropped, not run as whoever logs in next. (v3 has the same gap, sk_repl_headless_wait; reported, not changed.) Each a QEMU session red then green (amd64): midpull 111650 -> 112953, waitpull 111907 -> 113154, emergency 112524 -> 113609, typeahead 112248 -> 113359; headless 113800 and hotplug 114043 still pass. Accepted: three clean qemu boots to [zuse@Hera] ok>, POST 538/538, dict_hash 0xfec8c47cfc6f437f on all three; hotplug on aarch64 and riscv64; make -C v4 test test-32 sanitize hosted-check EXIT 0; make -C v4 test-32 0 failures. Co-Authored-By: Claude Opus 5.5 --- kernel/include/starkernel/v4/sk_v4_identity.h | 9 +++-- kernel/src/v4/sk_v4.c | 34 ++++++++++++++++--- kernel/src/v4/sk_v4_identity.c | 16 +++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/kernel/include/starkernel/v4/sk_v4_identity.h b/kernel/include/starkernel/v4/sk_v4_identity.h index dcbde69c..aef23de9 100644 --- a/kernel/include/starkernel/v4/sk_v4_identity.h +++ b/kernel/include/starkernel/v4/sk_v4_identity.h @@ -20,8 +20,13 @@ int sk_v4_identity_present(void); * with nothing typed. */ void sk_v4_identity_beat(void); -/* Headless: no prompt, no input, until Zuse's session begins (v3's - * sk_repl_headless_wait()). */ +/* The USB drives that have arrived or left, now, not waiting for the next + * beat: before each prompt, so that a drive pulled while the last line ran + * is seen before a prompt is shown. */ +void sk_v4_identity_check_now(void); + +/* Headless: no prompt, and what is typed is read and dropped, until Zuse's + * session begins (v3's sk_repl_headless_wait()). */ void sk_v4_identity_wait(void); #endif /* STARKERNEL_V4_SK_V4_IDENTITY_H */ diff --git a/kernel/src/v4/sk_v4.c b/kernel/src/v4/sk_v4.c index d4df370c..71c8a8df 100644 --- a/kernel/src/v4/sk_v4.c +++ b/kernel/src/v4/sk_v4.c @@ -77,8 +77,10 @@ static void sk_v4_serve(v4_node *node, unsigned request) /* Read a line from the keyboard: characters are echoed, backspace rubs one * out, Enter ends it. Returns its length; or -1 when, with nothing typed, - * Zuse's session has ended (her drive was pulled): the caller goes headless. - * While nothing is typed the idle beat runs, as v3's sk_console_readline(). */ + * Zuse's session has ended (her drive was pulled): the caller goes headless + * (not in a build with EMERGENCY_CONSOLE_ENABLED, whose console needs no + * login: v3's sk_console_readline() the same). While nothing is typed the + * idle beat runs, as v3's. */ static int sk_v4_readline(void) { int len = 0; @@ -87,7 +89,9 @@ static int sk_v4_readline(void) if (c < 0) { if (len == 0) { sk_v4_identity_beat(); +#if !EMERGENCY_CONSOLE_ENABLED if (!sk_v4_identity_present()) return -1; +#endif } else { heartbeat_service(); } @@ -134,9 +138,18 @@ void sk_v4_run(void (*chain)(void)) for (;;) { int len; int how; + int logged_out = 0; - /* no identity, no console: headless until Zuse's drive is checked */ +#if !EMERGENCY_CONSOLE_ENABLED + /* no identity, no console: headless until Zuse's drive is checked. + * The drives are looked at first, now: one pulled while the last + * line ran is seen before a prompt is shown (the identity gate's + * final review, item 1). Not in a build with + * EMERGENCY_CONSOLE_ENABLED, whose console needs no login (v3's + * kernel_main.c and repl.c the same; item 3). */ + sk_v4_identity_check_now(); if (!sk_v4_identity_present()) sk_v4_identity_wait(); +#endif console_puts(SK_V4_PROMPT); len = sk_v4_readline(); if (len < 0) continue; @@ -146,13 +159,26 @@ void sk_v4_run(void (*chain)(void)) * error, and then the line just typed is done (v4/boot.h). */ while (how == V4_BOOT_LINE_WAITING) { len = sk_v4_readline(); - if (len < 0) { sk_v4_identity_wait(); continue; } + if (len < 0) { + /* Zuse's session ended while the line waited: its wait is + * ended now, by an empty line, and not carried into the + * next session (Captain Bob, 2026-10-26: "end the waiting + * line at logout"). How it ended is shown; the empty line + * is then done, and shows nothing. */ + how = v4_boot_line(&boot, "", 0u); + if (how == V4_TEXT_ERROR) console_puts(" ERROR\n"); + else if (how == V4_TEXT_COMPLETED) console_puts(" ok\n"); + if (how == V4_TEXT_ERROR || how == V4_TEXT_COMPLETED) how = v4_boot_line(&boot, 0, 0); + logged_out = 1; + break; + } how = v4_boot_line(&boot, sk_v4_text, (unsigned)len); if (how == V4_TEXT_ERROR) console_puts(" ERROR\n" SK_V4_PROMPT); else if (how == V4_TEXT_COMPLETED) console_puts(" ok\n" SK_V4_PROMPT); else break; how = v4_boot_line(&boot, 0, 0); } + if (logged_out && (how == V4_TEXT_ERROR || how == V4_TEXT_COMPLETED)) continue; if (how == V4_TEXT_COMPLETED) console_puts(" ok\n"); else if (how == V4_TEXT_ERROR) console_puts(" ERROR\n"); else if (how == V4_BOOT_LINE_REFUSED) console_puts("Message refused\n ERROR\n"); /* the node's wire is full: error 19's words */ diff --git a/kernel/src/v4/sk_v4_identity.c b/kernel/src/v4/sk_v4_identity.c index 5de513aa..4619a518 100644 --- a/kernel/src/v4/sk_v4_identity.c +++ b/kernel/src/v4/sk_v4_identity.c @@ -191,10 +191,26 @@ void sk_v4_identity_beat(void) } } +void sk_v4_identity_check_now(void) +{ + g_last_beat = heartbeat_ticks(); + sk_v4_idle(); +} + +/* What was typed at a headless machine is no one's: it is read and dropped, + * so that it does not run as whoever logs in next (the identity gate's + * final review, item 4, 2026-10-26). */ +static void sk_v4_discard_input(void) +{ + while (console_getc() >= 0) { } +} + void sk_v4_identity_wait(void) { while (!g_zuse_session) { + sk_v4_discard_input(); sk_v4_identity_beat(); arch_relax(); } + sk_v4_discard_input(); }