(svn r16351) -Fix (r14773): signal handler could end in endless loop

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
smatz 16 years ago
parent 9af2e38d44
commit 5fe906e149

@ -235,14 +235,41 @@ static bool InitializeWindowsAndCaches()
return true; 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 * 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 * the savegame loading process; especially when there's problems with the
* NewGRFs that are required by the savegame. * 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 buffer[8192];
char *p = buffer; char *p = buffer;
p += seprintf(p, lastof(buffer), p += seprintf(p, lastof(buffer),
@ -272,6 +299,9 @@ void CDECL HandleSavegameLoadCrash(int unused)
} }
ShowInfo(buffer); 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() bool AfterLoadGame()
{ {
typedef void (CDECL *SignalHandlerPointer)(int); SetSignalHandlers();
SignalHandlerPointer prev_segfault = signal(SIGSEGV, HandleSavegameLoadCrash);
SignalHandlerPointer prev_abort = signal(SIGABRT, HandleSavegameLoadCrash);
TileIndex map_size = MapSize(); TileIndex map_size = MapSize();
Company *c; Company *c;
@ -437,8 +465,7 @@ bool AfterLoadGame()
if (_networking && gcf_res != GLC_ALL_GOOD) { if (_networking && gcf_res != GLC_ALL_GOOD) {
SetSaveLoadError(STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH); SetSaveLoadError(STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH);
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return false; return false;
} }
@ -490,8 +517,7 @@ bool AfterLoadGame()
if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, UINT_MAX)) { if (_game_mode == GM_NORMAL && !ClosestTownFromTile(0, UINT_MAX)) {
SetSaveLoadError(STR_NO_TOWN_IN_SCENARIO); SetSaveLoadError(STR_NO_TOWN_IN_SCENARIO);
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return false; return false;
} }
@ -554,8 +580,7 @@ bool AfterLoadGame()
SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET); SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET);
} else { } else {
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return false; return false;
} }
SB(_m[t].m6, 3, 3, st); SB(_m[t].m6, 3, 3, st);
@ -1813,8 +1838,7 @@ bool AfterLoadGame()
bool ret = InitializeWindowsAndCaches(); bool ret = InitializeWindowsAndCaches();
/* Restore the signals */ /* Restore the signals */
signal(SIGSEGV, prev_segfault); ResetSignalHandlers();
signal(SIGABRT, prev_abort);
return ret; return ret;
} }

Loading…
Cancel
Save