Skip to content

loopback_wake_test fails (child killed with signal 15, parent exits 1) on beast KVM x86 when a second concurrent loopback-TCP workload is present #692

Description

@ryanbreen

Summary

On the beast breenix-x86 KVM host, the testing,external_test_bins profile
intermittently reports

TEST_TALLY: exited=21 nonzero=2 failed=[loopback_wake_test_child:15,loopback_wake_test:1]

One of loopback_wake_test's children is killed with signal 15 and the
parent exits 1. scripts/x86-gate-verdict.sh fails the boot, correctly — the
allowlist is empty.

The parent's other children exit cleanly on the same boot:

Process 16 'loopback_wake_test_child_16' (thread 26) exited with code 15
Process 19 'loopback_wake_test_child_19' (thread 31) exited with code 0
Process 20 'loopback_wake_test_child_20' (thread 33) exited with code 0
Process 12 'loopback_wake_test'          (thread 22) exited with code 1

so one child of several is being torn down while its siblings are fine.

Serials

Preserved in-repo, one from each arm of an A/B battery:

  • docs/planning/green-program/sockets/serials/x86-loopback-red-armA-reorder-out-kernel-20260829.txt
  • docs/planning/green-program/sockets/serials/x86-loopback-red-armB-reorder-in-kernel-20260829.txt

The tally line is byte-identical in both.

Rate

Measured on beast breenix-x86, KVM, -cpu host, sequential boots, identical
build flags, three arms differing only in the kernel tree:

arm tree boots loopback red
A fix/568-poll-wedge (scheduler.rs identical to main) 8 1
B same + a Scheduler::schedule() reordering hunk 8 2
M pristine main @ 6d0d2ac5 8 0

What this rules in and out

It is not the scheduler reordering the #568 branch was carrying: the red
appears on both sides of the A/B with the same signature, so the hunk neither
causes nor prevents it. That hunk has since been reverted.

It is correlated with the added workload, not with a kernel change. The
only kernel difference between arm A and main is #568's sys_poll halt repair
(two hand-inlined halts replaced by the shared arch_halt_with_interrupts()
primitive). What arm A also adds is a userspace program: a second concurrent
loopback-TCP connection on port 9568 plus a fork(), running on every boot.
3/16 against 0/8 is suggestive, not conclusive, and the honest reading is that
the branch's extra loopback traffic makes an existing weakness in the loopback
wake path more likely to surface — not that it introduces one.

No fault is involved. No panic and no page-fault record appears in any of
the 24 boots across the three arms.

Where to start

The signal-15 teardown of one child while its siblings survive is the specific
thing to explain: who sends it, and why only under a concurrent second loopback
connection. loopback_wake_test and the loopback wake path itself
(#570 kloopbackd, and the pump structure test that pins its shape) are the
adjacent history.

Found while re-doing #568's evidence (green program, sockets); full A/B in
docs/planning/green-program/sockets/EVIDENCE-2026-08-29.md §5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions