- 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:
Christoph Oelckers 2011-07-15 13:26:36 +00:00
parent c8b8cdd13b
commit 080e769c76
5 changed files with 29 additions and 37 deletions

View file

@ -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 ();

View file

@ -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;

View file

@ -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;

View file

@ -246,6 +246,9 @@ 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 != NULL) // prev will be NULL if this actor gets deleted due to cleaning up from a broken savegame
{
if ((*prev = next)) // unlink from sector list if ((*prev = next)) // unlink from sector list
next->sprev = prev; next->sprev = prev;
snext = NULL; snext = NULL;
@ -267,6 +270,7 @@ void AActor::UnlinkFromWorld ()
sector_list = touching_sectorlist; sector_list = touching_sectorlist;
touching_sectorlist = NULL; //to be restored by P_SetThingPosition touching_sectorlist = NULL; //to be restored by P_SetThingPosition
} }
}
if (!(flags & MF_NOBLOCKMAP)) if (!(flags & MF_NOBLOCKMAP))
{ {

View file

@ -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();
} }