summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2009-05-18 12:01:13 +0000
committersmatz <smatz@openttd.org>2009-05-18 12:01:13 +0000
commit5fe906e14992f7a301ae94c357e80af076ab7a63 (patch)
treea81ef0ea906f06225fa9197183307d2b70dba7b2 /src
parent9af2e38d44abfe119b0c3e3b5647c6309cc979e2 (diff)
downloadopenttd-5fe906e14992f7a301ae94c357e80af076ab7a63.tar.xz
(svn r16351) -Fix (r14773): signal handler could end in endless loop
Diffstat (limited to 'src')
-rw-r--r--src/saveload/afterload.cpp50
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;
}