From bc6deab3f5d1c243754ede88f4064b27289203e3 Mon Sep 17 00:00:00 2001 From: rajames Date: Wed, 7 Oct 2026 12:25:35 -0400 Subject: [PATCH] fix(v4.0.0): a node blocked at a port with no one on it is given an error, not left there A node writing to a node that was stuck, and was then killed, stayed blocked for ever: killing a stuck node could cost its neighbours. And on the hosted and bare-metal products a write to an empty port, 5 7 PORT!, ended the program with "the node stopped". Now a node that can take an error, blocked writing to or reading from one port that nothing is wired to -- nothing ever was, or what was there has been killed or the wire cut -- has error 18, No one on that port, raised on it and goes on. A bare node waits as on the fabric; so does a node whose neighbour is asleep, and one reading "any port". test_host_unit.c: Hera kills node 14 while node 12 is blocked writing to it. It failed first: 12 stayed blocked. test_fabric.c: a bare node still waits. hosted-check types 5 7 PORT! and goes on; it failed first too. make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and riscv64 boot, POST 538 of 538, dict_hash 0x5f0a949a6fc8ef2b on all six: logs/20261007-121743, -122008, -122337. Co-Authored-By: Claude Opus 5.5 --- capsules/BLOCK_MAP.md | 2 +- capsules/v4/nucleus-64.f18 | Bin 52288 -> 52408 bytes docs/v4.0.0/MESH.md | 23 ++ .../amd64/qemu-amd64-20261007-121743.log | 160 ++++++++++++++ .../aarch64/qemu-aarch64-20261007-122008.log | 133 ++++++++++++ .../riscv64/qemu-riscv64-20261007-122337.log | 203 ++++++++++++++++++ v4/Makefile | 2 + v4/capsule/core.v4 | 2 +- v4/capsule/quit.v4 | 3 +- v4/include/v4/fabric.h | 12 ++ v4/include/v4/image.h | 5 + v4/include/v4/node.h | 10 + v4/src/fabric.c | 17 ++ v4/src/node.c | 10 + v4/system/boot.c | 6 +- v4/tests/test_fabric.c | 8 + v4/tests/test_host_unit.c | 17 ++ 17 files changed, 609 insertions(+), 4 deletions(-) create mode 100644 logs/20261007-121743/amd64/qemu-amd64-20261007-121743.log create mode 100644 logs/20261007-122008/aarch64/qemu-aarch64-20261007-122008.log create mode 100644 logs/20261007-122337/riscv64/qemu-riscv64-20261007-122337.log diff --git a/capsules/BLOCK_MAP.md b/capsules/BLOCK_MAP.md index 7737d3dc..733aa0a4 100644 --- a/capsules/BLOCK_MAP.md +++ b/capsules/BLOCK_MAP.md @@ -1,5 +1,5 @@ # Capsule Block Manifest — Auto-generated - + diff --git a/capsules/v4/nucleus-64.f18 b/capsules/v4/nucleus-64.f18 index f842ffa8e9030279f9678eb6dff32b227a3ca44e..1f73d1a15b58698e784d2dba069f37cc8840e7c5 100644 GIT binary patch delta 9141 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 G>HiPOdCI~7 delta 9102 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 : SQ DUP * ; + ok +ok> 7 SQ . 3 4 U* . . +49 0 12 ok +ok> T{ +UNKNOWN WORD: 'T{' + ERROR +ok> RS1 +UNKNOWN WORD: 'RS1' + ERROR +ok> COLD +FORTH-79 Cold Start +System initialized. + ok +ok> 3 4 U* . . +0 12 ok +ok> FORGET U* +Protected word + ERROR +ok> 9 KERNEL-WORD ASK9 ASK9 +Argument out of range + ERROR +ok> 1 BLOCK C@ . 2047 BLOCK C@ . +0 0 ok +ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ . +65 ok +ok> 3072 BLOCK C@ . +0 ok +ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS +Storage refused + ERROR +ok> 9999999 BLOCK +Block out of range + ERROR +ok> 5 7 PORT! +No one on that port + ERROR +ok> 1 2 + . +3 ok +ok> HERE . +8300 ok +ok> BYE +BYE: cold restart diff --git a/logs/20261007-122008/aarch64/qemu-aarch64-20261007-122008.log b/logs/20261007-122008/aarch64/qemu-aarch64-20261007-122008.log new file mode 100644 index 00000000..bfe8195a --- /dev/null +++ b/logs/20261007-122008/aarch64/qemu-aarch64-20261007-122008.log @@ -0,0 +1,133 @@ +UEFI firmware (version 2025.11-3ubuntu7.3 built at 15:40:26 on Sep 23 2026) +[=3hBdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x2,0x0): Not Found +BdsDxe: failed to load Boot0003 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:04.0-1" from PciRoot(0x0)/Pci(0x4,0x0)/USB(0x0,0x0): Not Found +BdsDxe: loading Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0) +BdsDxe: starting Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0) +[=3hStarKernel UEFI Loader +Loading kernel from ESP... +[CKPT 001] Entered efi_main - ConOut live +Collecting boot information... +[CKPT 004] Command line parsed +[CKPT 005] Kernel stack allocation decided +[CKPT 006] Boot info collected (ACPI table located) +[CKPT 007] GOP: linear framebuffer found +[CKPT 008] About to enter ExitBootServices retry loop + + + _____ _ _ __ _ + / ____| | | |/ / | | + | (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| | + \___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ | + ____) | || (_| | | | . \ __/ | | | | | __/ | + |_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_| + +LithosAnanke v2.1.0 +Architecture: aarch64 +Build: Oct 7 2026 12:19:41 + +UEFI BootServices: EXITED + +=== StarKernel Boot Information === +Memory map entries: 108 +Total memory: 4093 MB +Usable memory: 4054 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 1039358 + Free pages : 1037947 + Used pages : 1411 + Total MB : 4059 + Free MB : 4054 + Used MB : 5 + +VMM initialized (mapped RAM, CR3 switched) +VMM initialized (mapped RAM, CR3 switched) +VMM self-test: mapped OK at 0xffff800000000000 +VMM self-test complete. + +AArch64: running at EL1 +IDT installed. + +APIC: init... +PSCI: no DTB -- using HVC (QEMU virt-machine default) +GICv2: no DTB GIC node -- using QEMU virt-machine defaults +GICv2: distributor+CPU interface enabled, PPI 30 +APIC: init done + +Timer: init... +Timer: AArch64 generic timer initialised. +Timer: init done + +Kernel heap initialized. +Heap statistics: + Total bytes: 2147483608 + Free bytes: 2147483608 + Used bytes: 0 + Peak bytes: 0 + Heap base addr: 1207959552 + Heap end addr: 3355443200 + +Heartbeat: init... +Heartbeat: init done +Kernel initialization complete. +Boot successful! + +StarForth v4: one host node, the F18-derived engine +V4: capsule v4:nucleus-64.f18 signature: missing (unsigned) +PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0xbb8f7aba92a2f5dc capsule_hash=0xbb8f7aba92a2f5dc words=308 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x145ecc5563d10b54 +PARITY:V4_POST tests=538 pass=538 fail=0 +PARITY:V4_SYSTEM word_count=314 dict_hash=0x5f0a949a6fc8ef2b +PARITY:OK +POST: PASSED +[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks) +PCI: init... +virtio-blk: found device +Artemis: virtio-blk attached +[HADES][INFO ] [KRELTSC: 1354093] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b +ok> : SQ DUP * ; + ok +ok> 7 SQ . 3 4 U* . . +49 0 12 ok +ok> T{ +UNKNOWN WORD: 'T{' + ERROR +ok> RS1 +UNKNOWN WORD: 'RS1' + ERROR +ok> COLD +FORTH-79 Cold Start +System initialized. + ok +ok> 3 4 U* . . +0 12 ok +ok> FORGET U* +Protected word + ERROR +ok> 9 KERNEL-WORD ASK9 ASK9 +Argument out of range + ERROR +ok> 1 BLOCK C@ . 2047 BLOCK C@ . +0 0 ok +ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ . +65 ok +ok> 3072 BLOCK C@ . +0 ok +ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS +Storage refused + ERROR +ok> 9999999 BLOCK +Block out of range + ERROR +ok> 5 7 PORT! +No one on that port + ERROR +ok> 1 2 + . +3 ok +ok> HERE . +8300 ok +ok> BYE +BYE: cold restart diff --git a/logs/20261007-122337/riscv64/qemu-riscv64-20261007-122337.log b/logs/20261007-122337/riscv64/qemu-riscv64-20261007-122337.log new file mode 100644 index 00000000..d0ba38a1 --- /dev/null +++ b/logs/20261007-122337/riscv64/qemu-riscv64-20261007-122337.log @@ -0,0 +1,203 @@ + +OpenSBI v1.8 + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + +Platform Name : riscv-virtio,qemu +Platform Features : medeleg +Platform HART Count : 1 +Platform HART Protection : pmp +Platform IPI Device : aclint-mswi +Platform Timer Device : aclint-mtimer @ 10000000Hz +Platform Console Device : uart8250 +Platform HSM Device : --- +Platform PMU Device : --- +Platform Reboot Device : syscon-reboot +Platform Shutdown Device : syscon-poweroff +Platform Suspend Device : --- +Platform CPPC Device : --- +Firmware Base : 0x80000000 +Firmware Size : 321 KB +Firmware RW Offset : 0x40000 +Firmware RW Size : 65 KB +Firmware Heap Offset : 0x47000 +Firmware Heap Size : 37 KB (total), 0 KB (reserved), 12 KB (used), 23 KB (free) +Firmware Scratch Size : 4096 B (total), 1464 B (used), 2632 B (free) +Runtime SBI Version : 3.0 +Standard SBI Extensions : ipi,pmu,srst,sse,hsm,rfnc,fwft,time,base,legacy,dbcn,dbtr +Experimental SBI Extensions : none + +Domain0 Name : root +Domain0 Boot HART : 0 +Domain0 HARTs : 0* +Domain0 Region00 : 0x0000000080040000-0x000000008005ffff M: (F,R,W) S/U: () +Domain0 Region01 : 0x0000000080000000-0x000000008003ffff M: (F,R,X) S/U: () +Domain0 Region02 : 0x0000000000100000-0x0000000000100fff M: (I,R,W) S/U: (R,W) +Domain0 Region03 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W) +Domain0 Region04 : 0x0000000002000000-0x000000000200ffff M: (I,R,W) S/U: () +Domain0 Region05 : 0x000000000c400000-0x000000000c5fffff M: (I,R,W) S/U: (R,W) +Domain0 Region06 : 0x000000000c000000-0x000000000c3fffff M: (I,R,W) S/U: (R,W) +Domain0 Region07 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X) +Domain0 Next Address : 0x0000000020000000 +Domain0 Next Arg1 : 0x00000000bfe00000 +Domain0 Next Mode : S-mode +Domain0 SysReset : yes +Domain0 SysSuspend : yes + +Boot HART ID : 0 +Boot HART Domain : root +Boot HART Priv Version : v1.12 +Boot HART Base ISA : rv64imafdch +Boot HART ISA Extensions : sstc,zicntr,zihpm,zicboz,zicbom,sdtrig,svadu +Boot HART PMP Count : 16 +Boot HART PMP Granularity : 2 bits +Boot HART PMP Address Bits : 54 +Boot HART MHPM Info : 16 (0x0007fff8) +Boot HART Debug Triggers : 2 triggers +Boot HART MIDELEG : 0x0000000000001666 +Boot HART MEDELEG : 0x0000000000f4b509 +[=3hRISC-V EDK2 firmware version 2025.11-3ubuntu7.3 +Press ESCAPE within 5 seconds for boot options ERROR: C40000002:V03051002 I0 6D33944A-EC75-4855-A54D-809C75241F6C 83FFF850 +BdsDxe: failed to load Boot0001 "UEFI Misc Device" fr +om PciRoot(0x0)/Pci(0x1,0x0): Not Found +[=3hStarKernel UEFI Loader +Loading kernel from ESP... +[CKPT 001] Entered efi_main - ConOut live +Monolithic build - kernel linked directly +Collecting boot information... +CmdLine: parsed OK +[CKPT 004] Command line parsed +[CKPT 005] Kernel stack allocation decided +[CKPT 006] Boot info collected (ACPI table located) +GOP: linear framebuffer found +[CKPT 007] GOP: linear framebuffer found +[CKPT 008] About to enter ExitBootServices retry loop +Calling kernel_main (monolithic)... +riscv64 item 4.3.5a: satp state at kernel entry (before switch) + satp.MODE = 0x000000000000000a + satp.PPN = 0x00000000000bf868 + __kernel_start = 0x00000000bdca29f8 +riscv64: satp cleared -- Bare mode, explicit (item 4.3.5a) + + + _____ _ _ __ _ + / ____| | | |/ / | | + | (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| | + \___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ | + ____) | || (_| | | | . \ __/ | | | | | __/ | + |_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_| + +LithosAnanke v2.1.0 +Architecture: riscv64 +Build: Oct 7 2026 12:22:56 + +UEFI BootServices: EXITED + +=== StarKernel Boot Information === +Memory map entries: 100 +Total memory: 1020 MB +Usable memory: 975 MB +=================================== + +PMM initialized. +PMM statistics: + Total pages: 250273 + Free pages : 249621 + Used pages : 652 + Total MB : 977 + Free MB : 975 + Used MB : 2 + +VMM initialized (mapped RAM, CR3 switched) +VMM initialized (mapped RAM, CR3 switched) +VMM self-test: mapped OK at 0xffff800000000000 +VMM self-test complete. + +IDT installed. + +APIC: init... +PLIC: no DTB PLIC node -- using QEMU virt-machine default (base=0x0c000000) +PLIC: init (S-mode context 1, threshold=0) +APIC: init done + +Timer: init... +Timer: RISC-V time CSR @ 10000000 Hz (FALLBACK, no devicetree) +Timer: init done + +Kernel heap initialized. +Heap statistics: + Total bytes: 536870872 + Free bytes: 536870872 + Used bytes: 0 + Peak bytes: 0 + Heap base addr: 2214588416 + Heap end addr: 2751459328 + +Heartbeat: init... +Heartbeat: init done +Kernel initialization complete. +Boot successful! + +StarForth v4: one host node, the F18-derived engine +V4: capsule v4:nucleus-64.f18 signature: missing (unsigned) +PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0xbb8f7aba92a2f5dc capsule_hash=0xbb8f7aba92a2f5dc words=308 +V4: capsule v4:forth79.4th signature: missing (unsigned) +PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x145ecc5563d10b54 +PARITY:V4_POST tests=538 pass=538 fail=0 +PARITY:V4_SYSTEM word_count=314 dict_hash=0x5f0a949a6fc8ef2b +PARITY:OK +POST: PASSED +[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks) +PCI: init... +virtio-blk: found device +Artemis: virtio-blk attached +[HADES][INFO ] [KRELTSC: 37118739] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b +ok> : SQ DUP * ; + ok +ok> 7 SQ . 3 4 U* . . +49 0 12 ok +ok> T{ +UNKNOWN WORD: 'T{' + ERROR +ok> RS1 +UNKNOWN WORD: 'RS1' + ERROR +ok> COLD +FORTH-79 Cold Start +System initialized. + ok +ok> 3 4 U* . . +0 12 ok +ok> FORGET U* +Protected word + ERROR +ok> 9 KERNEL-WORD ASK9 ASK9 +Argument out of range + ERROR +ok> 1 BLOCK C@ . 2047 BLOCK C@ . +0 0 ok +ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ . +65 ok +ok> 3072 BLOCK C@ . +0 ok +ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS +Storage refused + ERROR +ok> 9999999 BLOCK +Block out of range + ERROR +ok> 5 7 PORT! +No one on that port + ERROR +ok> 1 2 + . +3 ok +ok> HERE . +8300 ok +ok> BYE +BYE: cold restart diff --git a/v4/Makefile b/v4/Makefile index 72d0c448..328ca604 100644 --- a/v4/Makefile +++ b/v4/Makefile @@ -198,6 +198,8 @@ hosted-check: $(foreach i,$(HOSTED_ISAS),$(BINDIR)/boot-$(i).txt) $(BINDIR)/star @printf 'RS1\nT{\nWORDS\n' | $(BINDIR)/starforth4-amd64 > $(BINDIR)/after-post-amd64.txt @grep -q "^ok> UNKNOWN WORD: 'RS1'$$" $(BINDIR)/after-post-amd64.txt || { echo "hosted-check: a word a POST case defined is still there"; exit 1; } @grep -q "^ok> UNKNOWN WORD: 'T{'$$" $(BINDIR)/after-post-amd64.txt || { echo "hosted-check: POST's harness is on the node"; exit 1; } + @printf '5 7 PORT!\n1 2 + .\n' | $(BINDIR)/starforth4-amd64 > $(BINDIR)/noone-amd64.txt 2>&1; true + @grep -q '^ok> No one on that port$$' $(BINDIR)/noone-amd64.txt && grep -q '^ok> 3 ok$$' $(BINDIR)/noone-amd64.txt || { echo "hosted-check: a write to a port with no one on it was not an error the node came back from"; cat $(BINDIR)/noone-amd64.txt | tail -4; exit 1; } @$(BINDIR)/starforth4-postfail < /dev/null > $(BINDIR)/postfail.txt; test $$? -ne 0 || { echo "hosted-check: a boot with a failing case did not fail"; exit 1; } @grep -q '^POST FAIL: fail.wrong out<5 5 $$' $(BINDIR)/postfail.txt || { echo "hosted-check: the failing case was not named"; cat $(BINDIR)/postfail.txt; exit 1; } @grep -q '^POST FAIL: fail.many outplace = places; f->capacity = capacity; + f->gone_error = 0; for (i = 0; i < capacity; i++) clear_place(&places[i]); } +void v4_fabric_gone_error(v4_fabric *f, v4_cell code) +{ + f->gone_error = code; +} + void v4_fabric_grow(v4_fabric *f, v4_place *places, unsigned capacity) { unsigned i; @@ -196,5 +202,16 @@ unsigned v4_fabric_step(v4_fabric *f) for (i = 0; i < f->capacity; i++) if (awake(f, i) && f->place[i].node->n.reading && !f->place[i].node->n.given) done += hand_over_read(f, i); + /* a node blocked at one port that nothing is wired to */ + if (f->gone_error != 0) + for (i = 0; i < f->capacity; i++) { + v4_node *n; + if (!awake(f, i)) continue; + n = &f->place[i].node->n; + if ((n->asking && f->place[i].wire[n->ask_port].kind == V4_WIRE_NONE) + || (n->reading && !n->given && n->read_port != V4_PORT_ANY && f->place[i].wire[n->read_port].kind == V4_WIRE_NONE)) + done += (unsigned)v4_node_port_gone(n, f->gone_error); + } + return done; } diff --git a/v4/src/node.c b/v4/src/node.c index fe39cf9c..a7f788ed 100644 --- a/v4/src/node.c +++ b/v4/src/node.c @@ -222,3 +222,13 @@ void v4_node_port_served(v4_node *n) { n->asking = 0; } + +int v4_node_port_gone(v4_node *n, v4_cell code) +{ + if (code == 0 || n->error_reg < 0 || n->fault_vector < 0 || n->stopped) return 0; + if (n->asking) n->asking = 0; + else if (n->reading && !n->given && n->read_port != V4_PORT_ANY) n->reading = 0; + else return 0; + v4_node_store(n, n->error_reg, code); /* raises it: P is the node's handler now */ + return 1; +} diff --git a/v4/system/boot.c b/v4/system/boot.c index 244f9b8e..e46ad608 100644 --- a/v4/system/boot.c +++ b/v4/system/boot.c @@ -139,13 +139,17 @@ static int run_line(const v4_boot *b, const char *text, unsigned len, char *keep } continue; } - if (n->asking) return V4_BOOT_LINE_STOPPED; /* a port with nothing on it */ + if (n->asking) { /* a port with no one on it: an error on the node */ + if (!v4_node_port_gone(n, V4_ERROR_NO_ONE)) return V4_BOOT_LINE_STOPPED; + continue; + } if (n->reading && !n->given) { if (sent < out.count && (n->read_port == CONSOLE_PORT || n->read_port == V4_PORT_ANY)) { v4_node_port_give(n, CONSOLE_PORT, out.word[sent++]); /* a word of the message to the node */ continue; } + if (n->read_port != CONSOLE_PORT && n->read_port != KERNEL_PORT && v4_node_port_gone(n, V4_ERROR_NO_ONE)) continue; /* reading one port, with no one on it */ return V4_BOOT_LINE_STOPPED; /* waiting for what will not come */ } if (v4_image_waiting(n, b->im)) { /* the text is reading the keyboard */ diff --git a/v4/tests/test_fabric.c b/v4/tests/test_fabric.c index 39a04672..d6000a45 100644 --- a/v4/tests/test_fabric.c +++ b/v4/tests/test_fabric.c @@ -273,6 +273,14 @@ int main(void) CHECK(ND(c)->n.mem[OUT] == 2, "who gets its next: %ld", (long)ND(c)->n.mem[OUT]); CHECK(ND(a)->n.asking && ND(a)->n.request == 3, "and the writer waits with its third"); CHECK(v4_fabric_unwire(&f, a, 0) && settle(100) == 0 && ND(a)->n.asking, "with the wire cut it goes on waiting"); + v4_fabric_gone_error(&f, 18); + CHECK(settle(100) == 0 && ND(a)->n.asking && ND(a)->n.faults == 0, "and still does when the fabric has an error for it: a bare node cannot take one"); + v4_node_error_attach(&ND(a)->n, OUT + 20); + v4_node_fault_attach(&ND(a)->n, 900); + CHECK(v4_fabric_step(&f) == 1 && !ND(a)->n.asking && ND(a)->n.fault_kind == V4_FAULT_RAISED && ND(a)->n.fault_addr == 18 + && ND(a)->n.p == 900 + (v4_cell)V4_FAULT_RAISED && ND(a)->n.mem[OUT + 20] == 18, + "a node that can take an error is let go, and the error is raised on it: its P is its handler"); + CHECK(!v4_node_port_gone(&ND(c)->n, 18), "a node that is not blocked at a port is not touched"); /* ---- asleep, awake, and removed, while looping; and a node born while others run ---- */ v4_fabric_init(&f, places, 4); diff --git a/v4/tests/test_host_unit.c b/v4/tests/test_host_unit.c index d7da3793..b5ac5ea1 100644 --- a/v4/tests/test_host_unit.c +++ b/v4/tests/test_host_unit.c @@ -380,6 +380,7 @@ int main(void) /* ---- Hera is born empty, and takes in the nucleus ---- */ v4_fabric_init(&f, places, PLACES); + v4_fabric_gone_error(&f, V4_ERROR_NO_ONE); place = host_born(0); CHECK(place == 0, "a node is born"); hera_place = (unsigned)place; @@ -498,6 +499,22 @@ int main(void) CHECK(strcmp(tell(10, "(LOST) @ ."), "0 ") == 0 && strcmp(tell(12, "(LOST) @ ."), "0 ") == 0, "and no message was let go"); CHECK(waiting(10) && waiting(11) && waiting(12) && waiting(13) && waiting(14), "all five are waiting at their ports again"); + /* ---- a node is killed while its neighbour is writing to it ---- */ + step_limit = 3000000ul; + CHECK(strcmp(tell(14, ": SPIN BEGIN 0 UNTIL ; SPIN"), "(still running)") == 0, "node 14 is stuck in a loop that never ends"); + CHECK(strcmp(tell(12, ": TO14 S\" 65 EMIT\" 14 SEND ; TO14"), "(still running)") == 0 && node_numbered(12)->asking, + "node 12, beside it, sends it text: 14 never reads, and 12 is blocked writing to it"); + { + unsigned born = born_count; + const char *r = tell(10, "(P4) @ NODE-KILL 65 EMIT"); + CHECK(strstr(printed, "A") != NULL && node_numbered(14) == NULL && born_count == born, "Hera kills node 14: \"%s\"", r); + } + CHECK(!node_numbered(12)->asking && !node_numbered(12)->stopped && waiting(12), "node 12 is no longer blocked: it is waiting at its ports"); + CHECK(strstr(printed, "No one on that port") != NULL, "what it was doing ended in an error, which said so: \"%s\"", printed); + step_limit = 30000000ul; + CHECK(strcmp(tell(12, "12 100 * ."), "1200 ") == 0 && strcmp(tell(13, "13 100 * ."), "1300 ") == 0 && strcmp(tell(10, "1 2 + ."), "3 ") == 0, "and everything else keeps running: \"%s\"", printed); + CHECK(strstr(tell(12, ": AGAIN14 S\" 65 EMIT\" 14 SEND ; AGAIN14"), "No one on that port") != NULL && waiting(12), "a later write to where node 14 was is an error at once, not a wait: \"%s\"", printed); + printf(" %d checks, %d failures\n", checks, failures); return failures != 0; }