the #35-class sweep + the games-night load crash: four lifecycle-window null-derefs guarded
THE CLASS (established by Gitea #35's 515 fix, confirmed growing tonight): code the binary could run bare because a pod's mission world always existed, crashing in the port's MP join/teardown/respawn windows where mission, player, or a roster link is briefly NULL. Swept every GetMissionPlayer()/ GetPlayerVehicle()/GetCurrentMission() chain in the tree (23+7 sites). GUARDED (the 515 pattern -- authentic behavior whenever the object exists, skip/degrade + loud log when mid-teardown): 1. DPLRenderer::SortAndReloadNameBitmaps -- runs in the round-STOP path (the end-of-round circle), raw mission+player+entity-manager derefs. 2. DPLRenderer::LoadOrdinalBitmaps -- called from (1); raw GetMissionPlayer()->GetInstance() evaluated on EVERY machine (the camera- director test derefs before it branches). 3. DPLRenderer::LoadNameBitmaps -- same window, raw GetPlayerCount() chain. 4. Reservoir::Reservoir master-gate block -- THE CAPTURED GAMES-NIGHT CRASH ([crash] btl4+0x4990d = this ctor inlined into CreateReservoirSubsystem, AV reading NULL+0x1d0): linkedSinks.Resolve() derefed raw; +0x1d0 is exactly the masterScale FILD of the resolved master heat-sink bank (heatSinkCount @0x1D0 -- the offset the crash named). Observed trigger: a DUPLICATE-PILOT egg (the seat-ghost bug put one identity in two seats) poisoning the ID registry, so Resolve() nulled during viewpoint-entity construction and at least two pods died loading the same egg. Now: loud '[spawn] FATAL-AVOIDED' + degrade to the inactive-copy shape. The duplicate-pilot ROOT CAUSE is the seat-ghost fix (tracked separately); this guard makes the failure survivable and self-identifying either way. CLASSIFIED SAFE, not touched: btl4mppr/btplayer/mechmppr/btl4gau3 chains (guarded or null-tolerant by design); APP.cpp's five Check(player) sites (mission state machine -- player exists by construction, original engine ordering); CAMMGR/CULTURAL GetCurrentMission chains (construction-time). VERIFIED: build clean (0 errors, no new unresolved externs); solo smoke on the guarded exe -- zero FATAL-AVOIDED lines (guards silent on the healthy path), subsystems simulating, no faults. STILL OWED: a full launch->stop rig cycle (exercises the guarded round-stop path live) and the duplicate-pilot-egg repro -- both blocked on port 1500 while the operator's console session is up. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c7dcdf26eb
commit
e28dcbc161
@@ -9963,6 +9963,22 @@ void
|
||||
|
||||
void DPLRenderer::SortAndReloadNameBitmaps()
|
||||
{
|
||||
//
|
||||
// NULL-GUARD (2026-07-26, the #35-class sweep). This resort runs in the
|
||||
// round-STOP path (the end-of-round "circle") and derefs the current
|
||||
// mission and the mission player raw -- the binary could, because a pod's
|
||||
// mission world always existed when it ran. The port's MP stop/teardown
|
||||
// windows (double-stop, abort-during-stop) can leave either briefly NULL
|
||||
// -- the exact shape of the 515 audio-clip crash. The refresh is
|
||||
// cosmetic; skip it when the world is mid-teardown.
|
||||
//
|
||||
if (application == 0
|
||||
|| application->GetCurrentMission() == 0
|
||||
|| application->GetMissionPlayer() == 0
|
||||
|| application->GetEntityManager() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Get the Entity Group of Players
|
||||
@@ -9993,6 +10009,15 @@ void DPLRenderer::SortAndReloadNameBitmaps()
|
||||
//
|
||||
void DPLRenderer::LoadOrdinalBitmaps()
|
||||
{
|
||||
// NULL-GUARD (2026-07-26, the #35-class sweep): runs from the round-stop
|
||||
// resort above; player/mission can be mid-teardown NULL in the port's MP
|
||||
// windows. Ordinals are the camera-director's cosmetic overlay -- skip.
|
||||
if (application == 0
|
||||
|| application->GetMissionPlayer() == 0
|
||||
|| application->GetCurrentMission() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Check if we have a Director on this machine,
|
||||
@@ -10062,6 +10087,12 @@ unsigned int*
|
||||
//
|
||||
void DPLRenderer::LoadNameBitmaps()
|
||||
{
|
||||
// NULL-GUARD (2026-07-26, the #35-class sweep): same teardown window as
|
||||
// SortAndReloadNameBitmaps above.
|
||||
if (application == 0 || application->GetCurrentMission() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int player_count = application->GetCurrentMission()->GetPlayerCount();
|
||||
for (int ii=0; ii<player_count; ++ii)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user