mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-02-04 13:23:46 +00:00
(svn r14773) -Fix-ish[FS#2469]: attach a signal handler during loading savegames to catch any crashes due to broken savegames/missing NewGRFs and tell the user about that instead of "just" crashing without explanation.
This commit is contained in:
parent
3c6add5293
commit
32583bd405
@ -84,6 +84,7 @@
|
|||||||
#include "water.h"
|
#include "water.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@ -1309,8 +1310,51 @@ static bool InitializeWindowsAndCaches()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void CDECL HandleSavegameLoadCrash(int unused)
|
||||||
|
{
|
||||||
|
char buffer[8192];
|
||||||
|
char *p = buffer;
|
||||||
|
p += seprintf(p, lastof(buffer),
|
||||||
|
"Loading your savegame caused OpenTTD to crash.\n"
|
||||||
|
"This is most likely caused by a missing NewGRF or a NewGRF that has been\n"
|
||||||
|
"loaded as replacement for a missing NewGRF. OpenTTD cannot easily\n"
|
||||||
|
"determine whether a replacement NewGRF is of a newer or older version.\n"
|
||||||
|
"It will load a NewGRF with the same GRF ID as the missing NewGRF. This\n"
|
||||||
|
"means that if the author makes incompatible NewGRFs with the same GRF ID\n"
|
||||||
|
"OpenTTD cannot magically do the right thing. In most cases OpenTTD will\n"
|
||||||
|
"load the savegame and not crash, but this is an exception.\n"
|
||||||
|
"Please load the savegame with the appropriate NewGRFs. When loading a\n"
|
||||||
|
"savegame still crashes when all NewGRFs are found you should file a\n"
|
||||||
|
"bug report. The missing NewGRFs are:\n");
|
||||||
|
|
||||||
|
for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
|
||||||
|
if (HasBit(c->flags, GCF_COMPATIBLE)) {
|
||||||
|
char buf[40];
|
||||||
|
md5sumToString(buf, lastof(buf), c->md5sum);
|
||||||
|
p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s. Tried another NewGRF with same GRF ID\n", BSWAP32(c->grfid), c->filename, buf);
|
||||||
|
}
|
||||||
|
if (c->status == GCS_NOT_FOUND) {
|
||||||
|
char buf[40];
|
||||||
|
md5sumToString(buf, lastof(buf), c->md5sum);
|
||||||
|
p += seprintf(p, lastof(buffer), "NewGRF %08X (%s) not found; checksum %s\n", BSWAP32(c->grfid), c->filename, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowInfo(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
bool AfterLoadGame()
|
bool AfterLoadGame()
|
||||||
{
|
{
|
||||||
|
typedef void (CDECL *SignalHandlerPointer)(int);
|
||||||
|
SignalHandlerPointer prev_segfault = signal(SIGSEGV, HandleSavegameLoadCrash);
|
||||||
|
SignalHandlerPointer prev_abort = signal(SIGABRT, HandleSavegameLoadCrash);
|
||||||
|
|
||||||
TileIndex map_size = MapSize();
|
TileIndex map_size = MapSize();
|
||||||
Company *c;
|
Company *c;
|
||||||
|
|
||||||
@ -1421,6 +1465,9 @@ bool AfterLoadGame()
|
|||||||
GRFListCompatibility gcf_res = IsGoodGRFConfigList();
|
GRFListCompatibility gcf_res = IsGoodGRFConfigList();
|
||||||
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 */
|
||||||
|
signal(SIGSEGV, prev_segfault);
|
||||||
|
signal(SIGABRT, prev_abort);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1468,6 +1515,9 @@ bool AfterLoadGame()
|
|||||||
/* make sure there is a town in the game */
|
/* make sure there is a town in the game */
|
||||||
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 */
|
||||||
|
signal(SIGSEGV, prev_segfault);
|
||||||
|
signal(SIGABRT, prev_abort);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1529,6 +1579,9 @@ bool AfterLoadGame()
|
|||||||
st = STATION_BUS;
|
st = STATION_BUS;
|
||||||
SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET);
|
SetStationGfx(t, gfx - 170 + GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET);
|
||||||
} else {
|
} else {
|
||||||
|
/* Restore the signals */
|
||||||
|
signal(SIGSEGV, prev_segfault);
|
||||||
|
signal(SIGABRT, prev_abort);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SB(_m[t].m6, 3, 3, st);
|
SB(_m[t].m6, 3, 3, st);
|
||||||
@ -2647,7 +2700,11 @@ bool AfterLoadGame()
|
|||||||
|
|
||||||
GamelogPrintDebug(1);
|
GamelogPrintDebug(1);
|
||||||
|
|
||||||
return InitializeWindowsAndCaches();
|
bool ret = InitializeWindowsAndCaches();
|
||||||
|
/* Restore the signals */
|
||||||
|
signal(SIGSEGV, prev_segfault);
|
||||||
|
signal(SIGABRT, prev_abort);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reload all NewGRF files during a running game. This is a cut-down
|
/** Reload all NewGRF files during a running game. This is a cut-down
|
||||||
|
@ -936,7 +936,7 @@ void ShowInfo(const char *str)
|
|||||||
#if defined(UNICODE)
|
#if defined(UNICODE)
|
||||||
/* We need to put the text in a seperate buffer because the default
|
/* We need to put the text in a seperate buffer because the default
|
||||||
* buffer in MB_TO_WIDE might not be large enough (512 chars) */
|
* buffer in MB_TO_WIDE might not be large enough (512 chars) */
|
||||||
wchar_t help_msgW[4096];
|
wchar_t help_msgW[8192];
|
||||||
#endif
|
#endif
|
||||||
ReleaseCapture();
|
ReleaseCapture();
|
||||||
_left_button_clicked =_left_button_down = false;
|
_left_button_clicked =_left_button_down = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user