mirror of
https://github.com/ioquake/ioq3.git
synced 2024-11-10 07:11:46 +00:00
Offer post-crash safe settings on a per-mod basis
Offer to restore settings when loading a mod that crashed, not the first mod that gets loaded after a crash. Before the first mod loaded (usually baseq3) would get the option even if missionpack or some other mod crashed. - Make pid files separate for each fs_game. - Remove/write pid every time switching fs_game. - Create path before writing pid file otherwise it fails on first run. - Show mod description.txt or fs_game instead of engine name in abnormal exit message. - Check com_fullyInitialized in Com_Error before removing PID, otherwise "ioquake3 --version" segfaults when accessing fs_gamevar->string (plus not fully initialized isn't really a normal shutdown).
This commit is contained in:
parent
1246d16834
commit
755b2f38f0
4 changed files with 87 additions and 41 deletions
|
@ -2776,17 +2776,7 @@ void Com_Init( char *commandLine ) {
|
||||||
|
|
||||||
Sys_Init();
|
Sys_Init();
|
||||||
|
|
||||||
if( Sys_WritePIDFile( ) ) {
|
Sys_InitPIDFile( FS_GetCurrentGameDir() );
|
||||||
#ifndef DEDICATED
|
|
||||||
const char *message = "The last time " CLIENT_WINDOW_TITLE " ran, "
|
|
||||||
"it didn't exit properly. This may be due to inappropriate video "
|
|
||||||
"settings. Would you like to start with \"safe\" video settings?";
|
|
||||||
|
|
||||||
if( Sys_Dialog( DT_YES_NO, message, "Abnormal Exit" ) == DR_YES ) {
|
|
||||||
Cvar_Set( "com_abnormalExit", "1" );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick a random port value
|
// Pick a random port value
|
||||||
Com_RandomBytes( (byte*)&qport, sizeof(int) );
|
Com_RandomBytes( (byte*)&qport, sizeof(int) );
|
||||||
|
|
|
@ -2482,6 +2482,33 @@ static char** Sys_ConcatenateFileLists( char **list0, char **list1 )
|
||||||
return cat;
|
return cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FS_GetModDescription
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void FS_GetModDescription( const char *modDir, char *description, int descriptionLen ) {
|
||||||
|
fileHandle_t descHandle;
|
||||||
|
char descPath[MAX_QPATH];
|
||||||
|
int nDescLen;
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
Com_sprintf( descPath, sizeof ( descPath ), "%s/description.txt", modDir );
|
||||||
|
nDescLen = FS_SV_FOpenFileRead( descPath, &descHandle );
|
||||||
|
|
||||||
|
if ( nDescLen > 0 && descHandle ) {
|
||||||
|
file = FS_FileForHandle(descHandle);
|
||||||
|
Com_Memset( description, 0, descriptionLen );
|
||||||
|
nDescLen = fread(description, 1, descriptionLen, file);
|
||||||
|
if (nDescLen >= 0) {
|
||||||
|
description[nDescLen] = '\0';
|
||||||
|
}
|
||||||
|
FS_FCloseFile(descHandle);
|
||||||
|
} else {
|
||||||
|
Q_strncpyz( description, modDir, descriptionLen );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
FS_GetModList
|
FS_GetModList
|
||||||
|
@ -2496,8 +2523,7 @@ int FS_GetModList( char *listbuf, int bufsize ) {
|
||||||
char **pFiles = NULL;
|
char **pFiles = NULL;
|
||||||
char **pPaks = NULL;
|
char **pPaks = NULL;
|
||||||
char *name, *path;
|
char *name, *path;
|
||||||
char descPath[MAX_OSPATH];
|
char description[MAX_OSPATH];
|
||||||
fileHandle_t descHandle;
|
|
||||||
|
|
||||||
int dummy;
|
int dummy;
|
||||||
char **pFiles0 = NULL;
|
char **pFiles0 = NULL;
|
||||||
|
@ -2571,28 +2597,13 @@ int FS_GetModList( char *listbuf, int bufsize ) {
|
||||||
nLen = strlen(name) + 1;
|
nLen = strlen(name) + 1;
|
||||||
// nLen is the length of the mod path
|
// nLen is the length of the mod path
|
||||||
// we need to see if there is a description available
|
// we need to see if there is a description available
|
||||||
descPath[0] = '\0';
|
FS_GetModDescription( name, description, sizeof( description ) );
|
||||||
strcpy(descPath, name);
|
nDescLen = strlen(description) + 1;
|
||||||
strcat(descPath, "/description.txt");
|
|
||||||
nDescLen = FS_SV_FOpenFileRead( descPath, &descHandle );
|
|
||||||
if ( nDescLen > 0 && descHandle) {
|
|
||||||
FILE *file;
|
|
||||||
file = FS_FileForHandle(descHandle);
|
|
||||||
Com_Memset( descPath, 0, sizeof( descPath ) );
|
|
||||||
nDescLen = fread(descPath, 1, 48, file);
|
|
||||||
if (nDescLen >= 0) {
|
|
||||||
descPath[nDescLen] = '\0';
|
|
||||||
}
|
|
||||||
FS_FCloseFile(descHandle);
|
|
||||||
} else {
|
|
||||||
strcpy(descPath, name);
|
|
||||||
}
|
|
||||||
nDescLen = strlen(descPath) + 1;
|
|
||||||
|
|
||||||
if (nTotal + nLen + 1 + nDescLen + 1 < bufsize) {
|
if (nTotal + nLen + 1 + nDescLen + 1 < bufsize) {
|
||||||
strcpy(listbuf, name);
|
strcpy(listbuf, name);
|
||||||
listbuf += nLen;
|
listbuf += nLen;
|
||||||
strcpy(listbuf, descPath);
|
strcpy(listbuf, description);
|
||||||
listbuf += nDescLen;
|
listbuf += nDescLen;
|
||||||
nTotal += nLen + nDescLen;
|
nTotal += nLen + nDescLen;
|
||||||
nMods++;
|
nMods++;
|
||||||
|
@ -3999,6 +4010,9 @@ void FS_Restart( int checksumFeed ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Q_stricmp(fs_gamedirvar->string, lastValidGame) ) {
|
if ( Q_stricmp(fs_gamedirvar->string, lastValidGame) ) {
|
||||||
|
Sys_RemovePIDFile( lastValidGame );
|
||||||
|
Sys_InitPIDFile( fs_gamedirvar->string );
|
||||||
|
|
||||||
// skip the q3config.cfg if "safe" is on the command line
|
// skip the q3config.cfg if "safe" is on the command line
|
||||||
if ( !Com_SafeMode() ) {
|
if ( !Com_SafeMode() ) {
|
||||||
Cbuf_AddText ("exec " Q3CONFIG_CFG "\n");
|
Cbuf_AddText ("exec " Q3CONFIG_CFG "\n");
|
||||||
|
|
|
@ -637,6 +637,8 @@ int FS_LoadStack( void );
|
||||||
int FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
|
int FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
|
||||||
int FS_GetModList( char *listbuf, int bufsize );
|
int FS_GetModList( char *listbuf, int bufsize );
|
||||||
|
|
||||||
|
void FS_GetModDescription( const char *modDir, char *description, int descriptionLen );
|
||||||
|
|
||||||
fileHandle_t FS_FOpenFileWrite( const char *qpath );
|
fileHandle_t FS_FOpenFileWrite( const char *qpath );
|
||||||
fileHandle_t FS_FOpenFileAppend( const char *filename );
|
fileHandle_t FS_FOpenFileAppend( const char *filename );
|
||||||
fileHandle_t FS_FCreateOpenPipeFile( const char *filename );
|
fileHandle_t FS_FCreateOpenPipeFile( const char *filename );
|
||||||
|
@ -1145,7 +1147,8 @@ typedef enum
|
||||||
|
|
||||||
dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title );
|
dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title );
|
||||||
|
|
||||||
qboolean Sys_WritePIDFile( void );
|
void Sys_RemovePIDFile( const char *gamedir );
|
||||||
|
void Sys_InitPIDFile( const char *gamedir );
|
||||||
|
|
||||||
/* This is based on the Adaptive Huffman algorithm described in Sayood's Data
|
/* This is based on the Adaptive Huffman algorithm described in Sayood's Data
|
||||||
* Compression book. The ranks are not actually stored, but implicitly defined
|
* Compression book. The ranks are not actually stored, but implicitly defined
|
||||||
|
|
|
@ -167,16 +167,29 @@ char *Sys_GetClipboardData(void)
|
||||||
Sys_PIDFileName
|
Sys_PIDFileName
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static char *Sys_PIDFileName( void )
|
static char *Sys_PIDFileName( const char *gamedir )
|
||||||
{
|
{
|
||||||
const char *homePath = Cvar_VariableString( "fs_homepath" );
|
const char *homePath = Cvar_VariableString( "fs_homepath" );
|
||||||
|
|
||||||
if( *homePath != '\0' )
|
if( *homePath != '\0' )
|
||||||
return va( "%s/%s", homePath, PID_FILENAME );
|
return va( "%s/%s/%s", homePath, gamedir, PID_FILENAME );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Sys_RemovePIDFile
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void Sys_RemovePIDFile( const char *gamedir )
|
||||||
|
{
|
||||||
|
char *pidFile = Sys_PIDFileName( gamedir );
|
||||||
|
|
||||||
|
if( pidFile != NULL )
|
||||||
|
remove( pidFile );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Sys_WritePIDFile
|
Sys_WritePIDFile
|
||||||
|
@ -184,9 +197,9 @@ Sys_WritePIDFile
|
||||||
Return qtrue if there is an existing stale PID file
|
Return qtrue if there is an existing stale PID file
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
qboolean Sys_WritePIDFile( void )
|
static qboolean Sys_WritePIDFile( const char *gamedir )
|
||||||
{
|
{
|
||||||
char *pidFile = Sys_PIDFileName( );
|
char *pidFile = Sys_PIDFileName( gamedir );
|
||||||
FILE *f;
|
FILE *f;
|
||||||
qboolean stale = qfalse;
|
qboolean stale = qfalse;
|
||||||
|
|
||||||
|
@ -212,6 +225,10 @@ qboolean Sys_WritePIDFile( void )
|
||||||
stale = qtrue;
|
stale = qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( FS_CreatePath( pidFile ) ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if( ( f = fopen( pidFile, "w" ) ) != NULL )
|
if( ( f = fopen( pidFile, "w" ) ) != NULL )
|
||||||
{
|
{
|
||||||
fprintf( f, "%d", Sys_PID( ) );
|
fprintf( f, "%d", Sys_PID( ) );
|
||||||
|
@ -223,6 +240,31 @@ qboolean Sys_WritePIDFile( void )
|
||||||
return stale;
|
return stale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Sys_InitPIDFile
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void Sys_InitPIDFile( const char *gamedir ) {
|
||||||
|
if( Sys_WritePIDFile( gamedir ) ) {
|
||||||
|
#ifndef DEDICATED
|
||||||
|
char message[1024];
|
||||||
|
char modName[MAX_OSPATH];
|
||||||
|
|
||||||
|
FS_GetModDescription( gamedir, modName, sizeof ( modName ) );
|
||||||
|
Q_CleanStr( modName );
|
||||||
|
|
||||||
|
Com_sprintf( message, sizeof (message), "The last time %s ran, "
|
||||||
|
"it didn't exit properly. This may be due to inappropriate video "
|
||||||
|
"settings. Would you like to start with \"safe\" video settings?", modName );
|
||||||
|
|
||||||
|
if( Sys_Dialog( DT_YES_NO, message, "Abnormal Exit" ) == DR_YES ) {
|
||||||
|
Cvar_Set( "com_abnormalExit", "1" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Sys_Exit
|
Sys_Exit
|
||||||
|
@ -238,13 +280,10 @@ static __attribute__ ((noreturn)) void Sys_Exit( int exitCode )
|
||||||
SDL_Quit( );
|
SDL_Quit( );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( exitCode < 2 )
|
if( exitCode < 2 && com_fullyInitialized )
|
||||||
{
|
{
|
||||||
// Normal exit
|
// Normal exit
|
||||||
char *pidFile = Sys_PIDFileName( );
|
Sys_RemovePIDFile( FS_GetCurrentGameDir() );
|
||||||
|
|
||||||
if( pidFile != NULL )
|
|
||||||
remove( pidFile );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NET_Shutdown( );
|
NET_Shutdown( );
|
||||||
|
|
Loading…
Reference in a new issue