Crash on startup in Congestion 64 MAP20, Hexen MAP40, etc.
Posted: Wed Oct 12, 2011 22:55
Yeah, you know, the megawad with the tiny 64x64 maps. To replicate the crash, make sure you are loading dynamic lights.
As far as I can tell, the problem is caused by this chain of events:
In my tests, the value of partner was consistently 0xC8, though I guess it might change on another computer. Regardless, it is non-NULL yet clearly far too low to be a valid pointer to the program's allocated memory.
Looking into it, it seems partner segs are initialized in gl_PreprocessLevel(). However, CollectWithinRadius() can be called before the level is preprocessed, for example through this chain: P_SpawnThings -> SpawnMapThing -> P_SpawnMapThing -> AActor::StaticSpawn -> FGLInterface::StateChanged -> gl_SetActorLights -> gl_AttachLight -> FLightDefaults::ApplyProperties -> ADynamicLight::SetOffset -> ADynamicLight::UpdateLocation -> ADynamicLight::LinkLight -> ADynamicLight::CollectWithinRadius
Since P_SetupLevel calls P_SpawnThings before it calls Renderer->PreprocessLevel, this might be the chain of function calls responsible for the crash. I haven't debugged the trace thoroughly yet so I'm not sure it's the path taken to the crash, but it seems possible.
I'll look more into it tomorrow.
As far as I can tell, the problem is caused by this chain of events:
- When the player is spawned in vanilla, the pawn telefrags monsters. Whenever a monster is met in Congestion 64, the bounding boxes overlap. Normally the level design is cramped enough that you don't realize that you're stuck until you've disposed of the monster anyway; but in ZDoom the monsters are just killed instantly.
- On MAP20, the monster of the level is a lost soul. Lost souls have a dynamic light attached to them.
- Dying updates the dynamic light, and makes the crash happens. On an earlier level, there is a barrel, which also has a dynamic light attached, but it does not have its state changed in the very first gametic and nothing bad happens.
Code: Select all
seg_t *partner = seg->PartnerSeg;
if (partner)
{
subsector_t *sub = partner->Subsector;
if (sub != NULL && sub->validcount!=::validcount)
Looking into it, it seems partner segs are initialized in gl_PreprocessLevel(). However, CollectWithinRadius() can be called before the level is preprocessed, for example through this chain: P_SpawnThings -> SpawnMapThing -> P_SpawnMapThing -> AActor::StaticSpawn -> FGLInterface::StateChanged -> gl_SetActorLights -> gl_AttachLight -> FLightDefaults::ApplyProperties -> ADynamicLight::SetOffset -> ADynamicLight::UpdateLocation -> ADynamicLight::LinkLight -> ADynamicLight::CollectWithinRadius
Since P_SetupLevel calls P_SpawnThings before it calls Renderer->PreprocessLevel, this might be the chain of function calls responsible for the crash. I haven't debugged the trace thoroughly yet so I'm not sure it's the path taken to the crash, but it seems possible.
I'll look more into it tomorrow.