From e7e3265c477b7419902a678026eba638e4ad3339 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 22 Sep 2026 13:53:57 -0400 Subject: [PATCH] [MG_Remote] (P7): the wire client's death notice is installed for any backend, not just Espryt WireTables.cpp:740 installed the client-side object_death emitter only when ActiveBackendType == DirectGLES. P6.5 wrote that because DirectGLES was the only backend with a two-process lane, so the condition read as "the case this can happen in" rather than as a policy - and under a Magma spawn or tcp client it is a silent hole of exactly the shape P6.5 closed for Espryt: no notice installed, NotifyAndFree drops every object_death before freeing the slot, and CtWireScenario's two death cases report ObjectDeaths=0 and prove nothing. The two remaining conditions carry P6.5's intent, both halves of it: Transport == Spawn (this is the remote client, the one with no local twin table; under inproc the backend's own dispatcher is the right one) and GetStateObjectDeathOps() == nullptr (whoever installed first keeps the notice). RED-ONCE: with the install site short-circuited, both DirectGLES spawn death cases red on CtWireScenario.cpp:187/:246 with Expected: (afterCounters.deaths) > (deathsBefore), actual: 0 vs 0 which is the silent zero this closes. Restored and green. WHAT IT DOES NOT DO is give Magma a death table - that is wave 2 package C. But it already does more than the plan predicted: with CtWireScenario's own BackendName() != "DirectGLES" skip guard temporarily lifted (a probe, not committed), both DirectVulkan SPAWN death cases PASS, while the DirectVulkan inproc arm still fails. So the two-process Magma death path works today and the remaining gap is the inproc arm alone. Recorded in the package note; narrowing that skip guard is package C's call and its file. --- MobileGL/MG_Remote/Client/WireTables.cpp | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/MobileGL/MG_Remote/Client/WireTables.cpp b/MobileGL/MG_Remote/Client/WireTables.cpp index fa153d65..38d0ceba 100644 --- a/MobileGL/MG_Remote/Client/WireTables.cpp +++ b/MobileGL/MG_Remote/Client/WireTables.cpp @@ -737,8 +737,34 @@ namespace MobileGL::MG_Remote::Client { // client emitter, NotifyAndFree silently drops object_death before // freeing the slot. Keep inproc's existing backend dispatcher, and give // the remote client the same wire delivery without a local twin table. + // + // P7 PACKAGE L: THE BACKEND TEST IS GONE, AND ITS ABSENCE IS THE POINT. P6.5 wrote + // `ActiveBackendType == DirectGLES` because DirectGLES was the only backend with a + // two-process lane, so the condition read as "the case this can happen in" rather than + // as a policy. Under a Magma spawn or tcp client it is a silent hole of exactly the + // shape P6.5 closed for Espryt: CtWireScenario's two death cases would report + // ObjectDeaths=0 and PASS NOTHING, because no notice was ever installed and + // NotifyAndFree would drop every object_death before freeing the slot - a green that + // means "the mechanism is absent". MEASURED on this tree: with the install site + // disabled, both DirectGLES spawn death cases red on CtWireScenario.cpp:187/:246 with + // `Expected: (afterCounters.deaths) > (deathsBefore), actual: 0 vs 0`. + // + // THE REMAINING TWO CONDITIONS STILL CARRY P6.5's INTENT, both halves of it: + // * Transport == Spawn: this is the REMOTE client, the one with no local twin table. + // Under inproc the server role is a thread in this process and its backend's own + // dispatcher is the right one. + // * GetStateObjectDeathOps() == nullptr: whoever installed first keeps the notice. + // That is what "keep inproc's existing backend dispatcher" meant, and it is also + // what keeps this from stomping a backend that installs ops of its own later. + // + // WHAT THIS DOES *NOT* DO IS GIVE MAGMA A DEATH TABLE. Magma installs no + // StateObjectDeathOps at all (wave 2 package C mirrors g_glesStateObjectDeathOps for + // it); until it does, the client-side emitter installed here still asks + // MGPipeSlots().FindByLifetimeId for a handle, gets a null one for an object Magma + // never routed, and emits nothing. The count under Magma may therefore still be 0 - + // but it is now 0 because no object crossed, which the lane can see and attribute, + // instead of 0 because nobody was listening, which it could not. if (MG_Config::Transport == MG_Config::TransportMode::Spawn && - MG_Config::ActiveBackendType == BackendType::DirectGLES && MG_State::GLState::GetStateObjectDeathOps() == nullptr) { MG_State::GLState::SetStateObjectDeathOps(&kClientStateObjectDeathOps); }