- try to keep the engine stable for as long as possible if a VM exception occurs in OnDestroy while running a cleanup.

This will still crash, but run long enough for the exception message to be visible.
This commit is contained in:
Christoph Oelckers 2022-10-20 16:48:18 +02:00
parent 936e89e3d4
commit b6c5232fea
6 changed files with 12 additions and 11 deletions

View file

@ -1069,7 +1069,7 @@ static void G_FullConsole()
primaryLevel->Music = ""; primaryLevel->Music = "";
S_Start(); S_Start();
S_StopMusic(true); S_StopMusic(true);
P_FreeLevelData(); P_FreeLevelData(false);
} }
} }

View file

@ -130,7 +130,7 @@ struct FLevelLocals
void AddScroller(int secnum); void AddScroller(int secnum);
void SetInterMusic(const char *nextmap); void SetInterMusic(const char *nextmap);
void SetMusicVolume(float v); void SetMusicVolume(float v);
void ClearLevelData(); void ClearLevelData(bool fullgc = true);
void ClearPortals(); void ClearPortals();
bool CheckIfExitIsGood(AActor *self, level_info_t *newmap); bool CheckIfExitIsGood(AActor *self, level_info_t *newmap);
void FormatMapName(FString &mapname, const char *mapnamecolor); void FormatMapName(FString &mapname, const char *mapnamecolor);

View file

@ -279,7 +279,7 @@ void FLevelLocals::ClearPortals()
// //
//========================================================================== //==========================================================================
void FLevelLocals::ClearLevelData() void FLevelLocals::ClearLevelData(bool fullgc)
{ {
{ {
auto it = GetThinkerIterator<AActor>(NAME_None, STAT_TRAVELLING); auto it = GetThinkerIterator<AActor>(NAME_None, STAT_TRAVELLING);
@ -291,7 +291,7 @@ void FLevelLocals::ClearLevelData()
} }
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
Thinkers.DestroyAllThinkers(); Thinkers.DestroyAllThinkers(fullgc);
ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process. ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
total_monsters = total_items = total_secrets = total_monsters = total_items = total_secrets =
@ -383,13 +383,13 @@ void FLevelLocals::ClearLevelData()
// //
//========================================================================== //==========================================================================
void P_FreeLevelData () void P_FreeLevelData (bool fullgc)
{ {
R_FreePastViewers(); R_FreePastViewers();
for (auto Level : AllLevels()) for (auto Level : AllLevels())
{ {
Level->ClearLevelData(); Level->ClearLevelData(fullgc);
} }
// primaryLevel->FreeSecondaryLevels(); // primaryLevel->FreeSecondaryLevels();
} }

View file

@ -143,7 +143,7 @@ bool P_CheckMapData(const char * mapname);
void P_SetupLevel (FLevelLocals *Level, int position, bool newGame); void P_SetupLevel (FLevelLocals *Level, int position, bool newGame);
void P_LoadLightmap(MapData *map); void P_LoadLightmap(MapData *map);
void P_FreeLevelData(); void P_FreeLevelData(bool fullgc = true);
// Called by startup code. // Called by startup code.
void P_Init (void); void P_Init (void);

View file

@ -271,7 +271,7 @@ void FThinkerCollection::RunThinkers(FLevelLocals *Level)
// //
//========================================================================== //==========================================================================
void FThinkerCollection::DestroyAllThinkers() void FThinkerCollection::DestroyAllThinkers(bool fullgc)
{ {
int i; int i;
bool error = false; bool error = false;
@ -285,11 +285,12 @@ void FThinkerCollection::DestroyAllThinkers()
} }
} }
error |= Thinkers[MAX_STATNUM + 1].DoDestroyThinkers(); error |= Thinkers[MAX_STATNUM + 1].DoDestroyThinkers();
GC::FullGC(); if (fullgc) GC::FullGC();
if (error) if (error)
{ {
ClearGlobalVMStack(); ClearGlobalVMStack();
I_Error("DestroyAllThinkers failed"); if (fullgc) I_Error("DestroyAllThinkers failed");
else I_FatalError("DestroyAllThinkers failed");
} }
} }

View file

@ -79,7 +79,7 @@ struct FThinkerCollection
} }
void RunThinkers(FLevelLocals *Level); // The level is needed to tick the lights void RunThinkers(FLevelLocals *Level); // The level is needed to tick the lights
void DestroyAllThinkers(); void DestroyAllThinkers(bool fullgc = true);
void SerializeThinkers(FSerializer &arc, bool keepPlayers); void SerializeThinkers(FSerializer &arc, bool keepPlayers);
void MarkRoots(); void MarkRoots();
DThinker *FirstThinker(int statnum); DThinker *FirstThinker(int statnum);