From f6a0bd3024a7126e7fadf47fc5facf182cb1ef34 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Mon, 21 Sep 2026 12:42:03 -0400 Subject: [PATCH] [MG_Remote] (P6/dl): D5c - a bell that can wake itself cannot hear a death Measured while running the 78-entry spawn matrix, not predicted. minecraft-1.21.4-fabric-iris-iterationrp-in-world kills the SERVER process outright on this machine - llvmpipe cannot lower the shader pack's %llvm.x86.vcvtps2ph.256 and aborts at call 159429 - and the client did NOT take the SessionWait::ShutDown path, which already exists and is already correct. It sat out the full 120 s and reported Fatal{BarrierTimeout, "ResourceRespecify"}: the wrong diagnosis, at two minutes a case, for a server that had been gone since the first second. The same trace fails in 3 s under monolith. The cause is structural and is the price of `sm`'s two-fd bell. The client parks on clientBell[0] and rings ITSELF through clientBell[1], so it holds both ends of that socketpair. EOF arrives only when every writer closes and the client is one of them, so that descriptor can never hang up no matter what happens to the peer. `dl` therefore needs a witness descriptor whose far end only the server holds, polled beside the park fd and never read from, whose POLLHUP/EOF latches Dead(). The control socket already is exactly that, so no new descriptor is needed. This is NOT a defect in `sm`: holding both ends is what self-notification requires, and without it the server's control pump could not wake its own apply thread - the bug that cost this branch an afternoon. The mistake would be assuming one descriptor can answer both questions. Recorded rather than fixed: it turns no red case green, and the only case that reaches it fails identically in all three arms for a reason that is not MobileGL's. `dl` owns the fix and S2 already names the red-once for it. Co-Authored-By: Claude Opus 5 --- MobileGL/MG_Remote/CONTRACT-P6.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MobileGL/MG_Remote/CONTRACT-P6.md b/MobileGL/MG_Remote/CONTRACT-P6.md index 7d8608ae..3e8ef7fc 100644 --- a/MobileGL/MG_Remote/CONTRACT-P6.md +++ b/MobileGL/MG_Remote/CONTRACT-P6.md @@ -313,6 +313,26 @@ is bounded by `MOBILEGL_IPC_CONTROL_TIMEOUT_MS` (default 5000) and its expiry is client consults the doorbell's death latch — dead latches device-lost, alive-but-silent is a named diagnostic. Packages: `cp` (a), `dl` (b). +> **D5c — the client's self-bell CANNOT witness the server's death, and `sm` is why.** Measured, not +> predicted: `minecraft-1.21.4-fabric-iris-iterationrp-in-world` kills the *server* process outright +> on this machine (llvmpipe: `LLVM ERROR: Cannot select: intrinsic %llvm.x86.vcvtps2ph.256`, SIGABRT +> at call 159429), and the client did **not** take the `SessionWait::ShutDown` path that already +> exists and is already correct. It sat out the full 120 s and reported +> `Fatal{BarrierTimeout, "ResourceRespecify"}` — the wrong diagnosis, at 120 s a case, for a server +> that had been gone since the first second. Under monolith the same trace fails in 3 s. +> +> The cause is structural and is the price of the two-fd bell: the client parks on `clientBell[0]` +> (slot 5) and rings *itself* through `clientBell[1]` (slot 6), so it holds **both ends** of that +> socketpair. EOF arrives only when every writer closes, and the client is one of them — so that +> descriptor can never hang up, no matter what happens to the peer. A bell that can wake itself is +> a bell that cannot hear a death. +> +> **`dl` therefore needs a witness descriptor whose far end only the SERVER holds**, polled beside +> the park fd and never read from, whose `POLLHUP`/EOF latches `Dead()`. The control socket is +> already exactly that and needs no new descriptor. The fix does not belong to `sm`: holding both +> ends is required for self-notification and is not the defect — assuming one descriptor could +> answer both questions is. + --- ## §6 The control plane (`cp`)