Defer RunMission until the mission load is ready (silent launch crash)

The relay fires the RunMission pair a fixed 20s after the egg ACK -- but
the ACK happens at egg RECEIPT, and a long mission load (glass + dev
gauges on a busy box measured ~50s) is still in LoadingMission when the
launch lands.  L4Application::RunMissionMessageHandler's default case
Fail()ed on that state -- an abort() the 1995 code could afford because
the real console launched operator-paced -- which presented as a SILENT
crash at mission start (c0000409, no WER record; cdb stack:
ucrtbase!abort <- RunMissionMessageHandler <- RoutePacket; 3/3
reproducible; matches the field report's 464 crash that died
mid-LOD-load).

The default case now DEFERS: re-post the message to ourselves at +1s
(the VehicleDead re-post pattern) until the ladder reaches
WaitingForLaunch, bounded at 120 deferrals so a truly wedged load still
surfaces the original Fail.  Verified: the crashing console-shaped run
deferred 104x through its ~50s load, then launched, rendered (scene
LIVE) and ran clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-22 17:19:28 -05:00
co-authored by Claude Opus 4.8
parent 66f22fb923
commit 638cfca18d
2 changed files with 37 additions and 0 deletions
+24
View File
@@ -610,6 +610,30 @@ void
break;
default:
//
// LAUNCH/LOAD RACE (2026-07-22): the relay sends the RunMission pair
// a fixed settle after the egg ACK, but a long mission load (glass +
// dev gauges on a busy box) can still be in LoadingMission when it
// lands -- the 1995 console never hit this state (the operator
// launched much later), so it Fail()ed = the "silent crash at
// mission launch" (c0000409 abort; 3/3 reproduced under cdb).
// DEFER instead: re-post the message to ourselves at +1s until the
// ladder reaches WaitingForLaunch (the VehicleDead re-post pattern).
// Bounded so a truly wedged load still surfaces the original Fail.
{
static int s_launch_deferrals = 0;
if (++s_launch_deferrals <= 120)
{
DEBUG_STREAM << "[launch] RunMission arrived in state "
<< (int)GetApplicationState()
<< " (still loading) -- deferred +1s ("
<< s_launch_deferrals << ")" << std::endl << std::flush;
Time when = Now();
when += 1.0f;
Post(HighEventPriority, this, message, when);
return; // base handler runs when ready
}
}
Fail("Application::RunMissionMessageHandler - Not ready to run!\n");
break;
}