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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
668abc48e6
commit
6452c540a2
@@ -20,8 +20,13 @@ int sk_v4_identity_present(void);
|
|||||||
* with nothing typed. */
|
* with nothing typed. */
|
||||||
void sk_v4_identity_beat(void);
|
void sk_v4_identity_beat(void);
|
||||||
|
|
||||||
/* Headless: no prompt, no input, until Zuse's session begins (v3's
|
/* The USB drives that have arrived or left, now, not waiting for the next
|
||||||
* sk_repl_headless_wait()). */
|
* 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);
|
void sk_v4_identity_wait(void);
|
||||||
|
|
||||||
#endif /* STARKERNEL_V4_SK_V4_IDENTITY_H */
|
#endif /* STARKERNEL_V4_SK_V4_IDENTITY_H */
|
||||||
|
|||||||
+30
-4
@@ -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
|
/* 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,
|
* 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.
|
* 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(). */
|
* (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)
|
static int sk_v4_readline(void)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -87,7 +89,9 @@ static int sk_v4_readline(void)
|
|||||||
if (c < 0) {
|
if (c < 0) {
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
sk_v4_identity_beat();
|
sk_v4_identity_beat();
|
||||||
|
#if !EMERGENCY_CONSOLE_ENABLED
|
||||||
if (!sk_v4_identity_present()) return -1;
|
if (!sk_v4_identity_present()) return -1;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
heartbeat_service();
|
heartbeat_service();
|
||||||
}
|
}
|
||||||
@@ -134,9 +138,18 @@ void sk_v4_run(void (*chain)(void))
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
int len;
|
int len;
|
||||||
int how;
|
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();
|
if (!sk_v4_identity_present()) sk_v4_identity_wait();
|
||||||
|
#endif
|
||||||
console_puts(SK_V4_PROMPT);
|
console_puts(SK_V4_PROMPT);
|
||||||
len = sk_v4_readline();
|
len = sk_v4_readline();
|
||||||
if (len < 0) continue;
|
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). */
|
* error, and then the line just typed is done (v4/boot.h). */
|
||||||
while (how == V4_BOOT_LINE_WAITING) {
|
while (how == V4_BOOT_LINE_WAITING) {
|
||||||
len = sk_v4_readline();
|
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);
|
how = v4_boot_line(&boot, sk_v4_text, (unsigned)len);
|
||||||
if (how == V4_TEXT_ERROR) console_puts(" ERROR\n" SK_V4_PROMPT);
|
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 if (how == V4_TEXT_COMPLETED) console_puts(" ok\n" SK_V4_PROMPT);
|
||||||
else break;
|
else break;
|
||||||
how = v4_boot_line(&boot, 0, 0);
|
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");
|
if (how == V4_TEXT_COMPLETED) console_puts(" ok\n");
|
||||||
else if (how == V4_TEXT_ERROR) console_puts(" ERROR\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 */
|
else if (how == V4_BOOT_LINE_REFUSED) console_puts("Message refused\n ERROR\n"); /* the node's wire is full: error 19's words */
|
||||||
|
|||||||
@@ -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)
|
void sk_v4_identity_wait(void)
|
||||||
{
|
{
|
||||||
while (!g_zuse_session) {
|
while (!g_zuse_session) {
|
||||||
|
sk_v4_discard_input();
|
||||||
sk_v4_identity_beat();
|
sk_v4_identity_beat();
|
||||||
arch_relax();
|
arch_relax();
|
||||||
}
|
}
|
||||||
|
sk_v4_discard_input();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user