diff options
author | smatz <smatz@openttd.org> | 2009-05-18 12:01:13 +0000 |
---|---|---|
committer | smatz <smatz@openttd.org> | 2009-05-18 12:01:13 +0000 |
commit | 5fe906e14992f7a301ae94c357e80af076ab7a63 (patch) | |
tree | a81ef0ea906f06225fa9197183307d2b70dba7b2 /src | |
parent | 9af2e38d44abfe119b0c3e3b5647c6309cc979e2 (diff) | |
download | openttd-5fe906e14992f7a301ae94c357e80af076ab7a63.tar.xz |
(svn r16351) -Fix (r14773): signal handler could end in endless loop
Diffstat (limited to 'src')
-rw-r--r-- | src/saveload/afterload.cpp | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index fbb1bdef4..0a86b701d 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -235,14 +235,41 @@ static bool InitializeWindowsAndCaches() return true; } +typedef void (CDECL *SignalHandlerPointer)(int); +static SignalHandlerPointer _prev_segfault = NULL; +static SignalHandlerPointer _prev_abort = NULL; + +static void CDECL HandleSavegameLoadCrash(int signum); + +/** + * Replaces signal handlers of SIGSEGV and SIGABRT + * and stores pointers to original handlers in memory. + */ +static void SetSignalHandlers() +{ + _prev_segfault = signal(SIGSEGV, HandleSavegameLoadCrash); + _prev_abort = signal(SIGABRT, HandleSavegameLoadCrash); +} + +/** + * Resets signal handlers back to original handlers. + */ +static void ResetSignalHandlers() +{ + signal(SIGSEGV, _prev_segfault); + signal(SIGABRT, _prev_abort); +} + /** * Signal handler used to give a user a more useful report for crashes during * the savegame loading process; especially when there's problems with the * NewGRFs that are required by the savegame. - * @param unused well... unused + * @param signum received signal */ -void CDECL HandleSavegameLoadCrash(int unused) +static void CDECL HandleSavegameLoadCrash(int signum) { + ResetSignalHandlers(); + char buffer[8192]; char *p = buffer; p += seprintf(p, lastof(buffer), @@ -272,6 +299,9 @@ void CDECL HandleSavegameLoadCrash(int unused) } ShowInfo(buffer); + + SignalHandlerPointer call = signum == SIGSEGV ? _prev_segfault : _prev_abort; + if (call != NULL) call(signum); } /** @@ -322,9 +352,7 @@ static void FixOwnerOfRailTrack(TileIndex t) bool AfterLoadGame() { - typedef void (CDECL *SignalHandlerPointer)(int); - SignalHandlerPointer prev_segfault = signal(SIGSEGV, HandleSavegameLoadCrash); - SignalHandlerPointer prev_abort = signal(SIGABRT, HandleSavegameLoadCrash); + SetSignalHandlers(); TileIndex map_size = MapSize(); Company *c; @@ -437,8 +465,7 @@ bool AfterLoadGame() if (_networking && gcf_res != GLC_ALL_GOOD) { SetSaveLoadError(STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH); /* Restore the signals */ - signal(SIGSEGV, prev_segfault); - signal(SIGABRT, prev_abort); + ResetSignalHandlers(); return false; } @@ -490,8 +517,7 @@ bool AfterLoadGame() if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, UINT_MAX)) { SetSaveLoadError(STR_NO_TOWN_IN_SCENARIO); /* Restore the signals */ - signal(SIGSEGV, prev_segfault); - signal(SIGABRT, prev_abort); + ResetSignalHandlers(); return false; } @@ -554,8 +580,7 @@ bool AfterLoadGame() SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET); } else { /* Restore the signals */ - signal(SIGSEGV, prev_segfault); - signal(SIGABRT, prev_abort); + ResetSignalHandlers(); return false; } SB(_m[t].m6, 3, 3, st); @@ -1813,8 +1838,7 @@ bool AfterLoadGame() bool ret = InitializeWindowsAndCaches(); /* Restore the signals */ - signal(SIGSEGV, prev_segfault); - signal(SIGABRT, prev_abort); + ResetSignalHandlers(); return ret; } |