mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- removed all asserts from the interpolation objects' Destroy methods. The condition will not be true after a failed savegame write occured.
- fixed: D_ErrorCleanup must clear 'savegamerestore'. - fixed: Cleaning up when loading a savegame failed while restoring the thinker list did not work. There were two issues: * removed the asserts in GC::SweepList because they get triggered by thinkers that were not fully initialized during loading. * AActor::UnlinkFromWorld may not assume that the sector list has been initialized when this function is called. SVN r3274 (trunk)
This commit is contained in:
parent
c8b8cdd13b
commit
080e769c76
5 changed files with 29 additions and 37 deletions
|
@ -912,6 +912,7 @@ void D_Display ()
|
||||||
|
|
||||||
void D_ErrorCleanup ()
|
void D_ErrorCleanup ()
|
||||||
{
|
{
|
||||||
|
savegamerestore = false;
|
||||||
screen->Unlock ();
|
screen->Unlock ();
|
||||||
bglobal.RemoveAllBots (true);
|
bglobal.RemoveAllBots (true);
|
||||||
D_QuitNetGame ();
|
D_QuitNetGame ();
|
||||||
|
|
|
@ -242,8 +242,10 @@ static DObject **SweepList(DObject **p, size_t count, size_t *finalize_count)
|
||||||
// be in a thinker list, then I need to add write barriers for every time a
|
// be in a thinker list, then I need to add write barriers for every time a
|
||||||
// thinker pointer is changed. This seems easier and perfectly reasonable, since
|
// thinker pointer is changed. This seems easier and perfectly reasonable, since
|
||||||
// a live thinker that isn't on a thinker list isn't much of a thinker.
|
// a live thinker that isn't on a thinker list isn't much of a thinker.
|
||||||
assert(!curr->IsKindOf(RUNTIME_CLASS(DThinker)) || (curr->ObjectFlags & OF_Sentinel));
|
|
||||||
assert(!curr->IsKindOf(RUNTIME_CLASS(DInterpolation)));
|
// However, this can happen during deletion of the thinker list while cleaning up
|
||||||
|
// from a savegame error so we can't assume that any thinker that gets here is an error.
|
||||||
|
|
||||||
curr->Destroy();
|
curr->Destroy();
|
||||||
}
|
}
|
||||||
curr->ObjectFlags |= OF_Cleanup;
|
curr->ObjectFlags |= OF_Cleanup;
|
||||||
|
|
|
@ -192,19 +192,10 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad)
|
||||||
statcount--;
|
statcount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (class CDoomError &err)
|
catch (class CDoomError &)
|
||||||
{
|
{
|
||||||
bSerialOverride = false;
|
bSerialOverride = false;
|
||||||
|
DestroyAllThinkers();
|
||||||
// DestroyAllThinkers cannot be called here. It will try to delete the corrupted
|
|
||||||
// object table left behind by the serializer and crash.
|
|
||||||
// Trying to continue is not an option here because the garbage collector will
|
|
||||||
// crash the next time it runs.
|
|
||||||
// Even making this a fatal error will crash but at least the message can be seen
|
|
||||||
// before the crash - which is not the case with all other options.
|
|
||||||
|
|
||||||
//DestroyAllThinkers();
|
|
||||||
I_FatalError("%s", err.GetMessage());
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
bSerialOverride = false;
|
bSerialOverride = false;
|
||||||
|
|
|
@ -246,26 +246,30 @@ void AActor::UnlinkFromWorld ()
|
||||||
// pointers, allows head node pointers to be treated like everything else
|
// pointers, allows head node pointers to be treated like everything else
|
||||||
AActor **prev = sprev;
|
AActor **prev = sprev;
|
||||||
AActor *next = snext;
|
AActor *next = snext;
|
||||||
if ((*prev = next)) // unlink from sector list
|
|
||||||
next->sprev = prev;
|
|
||||||
snext = NULL;
|
|
||||||
sprev = (AActor **)(size_t)0xBeefCafe; // Woo! Bug-catching value!
|
|
||||||
|
|
||||||
// phares 3/14/98
|
if (prev != NULL) // prev will be NULL if this actor gets deleted due to cleaning up from a broken savegame
|
||||||
//
|
{
|
||||||
// Save the sector list pointed to by touching_sectorlist.
|
if ((*prev = next)) // unlink from sector list
|
||||||
// In P_SetThingPosition, we'll keep any nodes that represent
|
next->sprev = prev;
|
||||||
// sectors the Thing still touches. We'll add new ones then, and
|
snext = NULL;
|
||||||
// delete any nodes for sectors the Thing has vacated. Then we'll
|
sprev = (AActor **)(size_t)0xBeefCafe; // Woo! Bug-catching value!
|
||||||
// put it back into touching_sectorlist. It's done this way to
|
|
||||||
// avoid a lot of deleting/creating for nodes, when most of the
|
|
||||||
// time you just get back what you deleted anyway.
|
|
||||||
//
|
|
||||||
// If this Thing is being removed entirely, then the calling
|
|
||||||
// routine will clear out the nodes in sector_list.
|
|
||||||
|
|
||||||
sector_list = touching_sectorlist;
|
// phares 3/14/98
|
||||||
touching_sectorlist = NULL; //to be restored by P_SetThingPosition
|
//
|
||||||
|
// Save the sector list pointed to by touching_sectorlist.
|
||||||
|
// In P_SetThingPosition, we'll keep any nodes that represent
|
||||||
|
// sectors the Thing still touches. We'll add new ones then, and
|
||||||
|
// delete any nodes for sectors the Thing has vacated. Then we'll
|
||||||
|
// put it back into touching_sectorlist. It's done this way to
|
||||||
|
// avoid a lot of deleting/creating for nodes, when most of the
|
||||||
|
// time you just get back what you deleted anyway.
|
||||||
|
//
|
||||||
|
// If this Thing is being removed entirely, then the calling
|
||||||
|
// routine will clear out the nodes in sector_list.
|
||||||
|
|
||||||
|
sector_list = touching_sectorlist;
|
||||||
|
touching_sectorlist = NULL; //to be restored by P_SetThingPosition
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & MF_NOBLOCKMAP))
|
if (!(flags & MF_NOBLOCKMAP))
|
||||||
|
|
|
@ -406,12 +406,10 @@ void DSectorPlaneInterpolation::Destroy()
|
||||||
{
|
{
|
||||||
if (ceiling)
|
if (ceiling)
|
||||||
{
|
{
|
||||||
assert(sector->interpolations[sector_t::CeilingMove] == this);
|
|
||||||
sector->interpolations[sector_t::CeilingMove] = NULL;
|
sector->interpolations[sector_t::CeilingMove] = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(sector->interpolations[sector_t::FloorMove] == this);
|
|
||||||
sector->interpolations[sector_t::FloorMove] = NULL;
|
sector->interpolations[sector_t::FloorMove] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,12 +568,10 @@ void DSectorScrollInterpolation::Destroy()
|
||||||
{
|
{
|
||||||
if (ceiling)
|
if (ceiling)
|
||||||
{
|
{
|
||||||
assert(sector->interpolations[sector_t::CeilingScroll] == this);
|
|
||||||
sector->interpolations[sector_t::CeilingScroll] = NULL;
|
sector->interpolations[sector_t::CeilingScroll] = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(sector->interpolations[sector_t::FloorScroll] == this);
|
|
||||||
sector->interpolations[sector_t::FloorScroll] = NULL;
|
sector->interpolations[sector_t::FloorScroll] = NULL;
|
||||||
}
|
}
|
||||||
Super::Destroy();
|
Super::Destroy();
|
||||||
|
@ -661,7 +657,6 @@ DWallScrollInterpolation::DWallScrollInterpolation(side_t *_side, int _part)
|
||||||
|
|
||||||
void DWallScrollInterpolation::Destroy()
|
void DWallScrollInterpolation::Destroy()
|
||||||
{
|
{
|
||||||
assert(side->textures[part].interpolation == this);
|
|
||||||
side->textures[part].interpolation = NULL;
|
side->textures[part].interpolation = NULL;
|
||||||
Super::Destroy();
|
Super::Destroy();
|
||||||
}
|
}
|
||||||
|
@ -746,7 +741,6 @@ DPolyobjInterpolation::DPolyobjInterpolation(FPolyObj *po)
|
||||||
|
|
||||||
void DPolyobjInterpolation::Destroy()
|
void DPolyobjInterpolation::Destroy()
|
||||||
{
|
{
|
||||||
assert(poly->interpolation == this);
|
|
||||||
poly->interpolation = NULL;
|
poly->interpolation = NULL;
|
||||||
Super::Destroy();
|
Super::Destroy();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue