Files
dtourolle 0e27339ab6 chore: update KPN — unconditional push wake, and the start() lock it exposed
Two commits on top of c9aa246.

6802328 fixes a lost wake in the channel itself: push fired push_callback_
only on the empty->non-empty edge, computed from a head_ sampled before the
item was published, so a pop landing in that window left the item in the ring
with the consumer idle and no wake outstanding. Absorbing, because every later
push then sees a non-empty ring and the edge never fires again. Firing
unconditionally is correct by construction — the callback runs after the
publishing store — and the redundant wakes are cheap, since on_input_ready
re-checks the level and the submit gate collapses a wake arriving mid-firing.

771b9f8 is the gap that change exposed. abbb2d4 guarded ThreadPool::submit
against stop(), which clears queues_, but missed that start() rebuilds the
same vector under no lock. A submission genuinely lands there — a network
starts nodes one at a time, and an already-started node fires into the next
one's channel, whose callback submits — and push_back can reallocate under a
reader that has already indexed it. Unobserved before; 4 races in one run
after callbacks became frequent enough during startup.

Verified: KPN 148/148, this repo 149/149, ThreadSanitizer clean across five
unit runs and two stress runs.

Not re-measured on a clip. The GPU has a driver/library version mismatch
(kernel module 610.43.03 against NVML 610.57 — an update without a reboot),
so scene_analyze aborts in cuInit before it decodes anything. The SuperHero-1
measurement recorded in c599e07 — exit 0, outran() 0, scenes.json and presence
byte-identical — stands against c9aa246; both commits added since are
concurrency fixes with no effect on pipeline semantics, but a re-run is worth
doing once the driver is sorted.

TRACES: AR-004 | SR-002
2026-08-06 22:59:18 +02:00
..