From 78d24e12a289f80fc5175426b7d56dc26d15fe70 Mon Sep 17 00:00:00 2001 From: danij Date: Sun, 8 Jan 2012 06:36:57 +0000 Subject: [PATCH] Fixed: Fatal error during game change An attempt was made to dereference a dangling pointer to the objlink blockmap once a map had been played and the game subsequently changed. The objlink blockmaps are allocated with a Zone purge level >= PU_MAP thus pointers to them will be invalid after a game change. --- doomsday/engine/portable/include/p_objlink.h | 11 +++++++++++ doomsday/engine/portable/src/dd_main.c | 4 ++-- doomsday/engine/portable/src/p_objlink.c | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/doomsday/engine/portable/include/p_objlink.h b/doomsday/engine/portable/include/p_objlink.h index 6279bcd5ce..357dd297fd 100644 --- a/doomsday/engine/portable/include/p_objlink.h +++ b/doomsday/engine/portable/include/p_objlink.h @@ -39,6 +39,17 @@ typedef enum { #define VALID_OBJTYPE(val) ((val) >= OT_MOBJ && (val) < NUM_OBJ_TYPES) +/** + * To be called during a game change/on shutdown to destroy the objlink + * blockmap. This is necessary because the blockmaps are allocated from + * the Zone with a >= PU_MAP purge level and access to them is handled + * with global pointers. + * + * \todo Encapsulate allocation of and access to the objlink blockmaps + * within de::Map + */ +void R_DestroyObjlinkBlockmap(void); + /** * Construct the objlink blockmap for the current map. */ diff --git a/doomsday/engine/portable/src/dd_main.c b/doomsday/engine/portable/src/dd_main.c index 6a8dc61d2d..7a25ea2b84 100644 --- a/doomsday/engine/portable/src/dd_main.c +++ b/doomsday/engine/portable/src/dd_main.c @@ -1073,7 +1073,7 @@ boolean DD_ChangeGame2(Game* game, boolean allowReload) Con_SaveDefaults(); LO_Clear(); - //R_DestroyObjlinks(); + R_DestroyObjlinkBlockmap(); R_ClearAnimGroups(); P_PtcShutdown(); @@ -1514,7 +1514,7 @@ int DD_Main(void) // Try to locate all required data files for all registered games. Con_InitProgress(200); - Con_Busy(BUSYF_STARTUP | BUSYF_PROGRESS_BAR | BUSYF_PROGRESS_BAR | (verbose? BUSYF_CONSOLE_OUTPUT : 0), + Con_Busy(BUSYF_STARTUP | BUSYF_PROGRESS_BAR | (verbose? BUSYF_CONSOLE_OUTPUT : 0), "Locating game resources...", DD_LocateAllGameResourcesWorker, 0); // Unless we reenter busy-mode due to automatic game selection, we won't be diff --git a/doomsday/engine/portable/src/p_objlink.c b/doomsday/engine/portable/src/p_objlink.c index 7596cd7407..e86d8f8d72 100644 --- a/doomsday/engine/portable/src/p_objlink.c +++ b/doomsday/engine/portable/src/p_objlink.c @@ -249,6 +249,23 @@ void R_InitObjlinkBlockmapForMap(void) ssecContacts = Z_Calloc(sizeof *ssecContacts * numSSectors, PU_MAPSTATIC, 0); } +void R_DestroyObjlinkBlockmap(void) +{ + int i; + for(i = 0; i < NUM_OBJ_TYPES; ++i) + { + objlinkblockmap_t* obm = chooseObjlinkBlockmap((objtype_t)i); + if(!obm->gridmap) continue; + Gridmap_Delete(obm->gridmap); + obm->gridmap = NULL; + } + if(ssecContacts) + { + Z_Free(ssecContacts); + ssecContacts = NULL; + } +} + int clearObjlinkBlock(void* obj, void* paramaters) { objlinkblock_t* block = (objlinkblock_t*)obj;