mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-02 23:41:51 +00:00
Implement Sys_ReLaunch() for Linux, refactor it
It now works on Linux so executing it doesn't freeze the game like described in https://github.com/RobertBeckebans/RBDOOM-3-BFG/issues/33 Furthermore, this function doesn't have any parameters anymore (on any platform) because the only thing supplied was the original program arguments +"+set com_skipIntroVideos 1" anyway - this is now done in Sys_ReLaunch() (also on Windows). Having the program arguments as one string is bad on Linux/POSIX because there it's expected that the program arguments are one C-string per argument.
This commit is contained in:
parent
98093a4e8d
commit
b044526ddb
5 changed files with 108 additions and 18 deletions
|
@ -219,12 +219,10 @@ void idMenuScreen_Shell_Stereoscopics::HideScreen( const mainMenuTransition_t tr
|
||||||
common->Dialog().ClearDialog( msg );
|
common->Dialog().ClearDialog( msg );
|
||||||
if( restart )
|
if( restart )
|
||||||
{
|
{
|
||||||
idStr cmdLine = Sys_GetCmdLine();
|
// DG: Sys_ReLaunch() doesn't need any options anymore
|
||||||
if( cmdLine.Find( "com_skipIntroVideos" ) < 0 )
|
// (the old way would have been unnecessarily painful on POSIX systems)
|
||||||
{
|
Sys_ReLaunch();
|
||||||
cmdLine.Append( " +set com_skipIntroVideos 1" );
|
// DG end
|
||||||
}
|
|
||||||
Sys_ReLaunch( ( void* )cmdLine.c_str(), cmdLine.Length() );
|
|
||||||
}
|
}
|
||||||
return idSWFScriptVar();
|
return idSWFScriptVar();
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,12 +232,10 @@ void idMenuScreen_Shell_SystemOptions::HideScreen( const mainMenuTransition_t tr
|
||||||
common->Dialog().ClearDialog( msg );
|
common->Dialog().ClearDialog( msg );
|
||||||
if( restart )
|
if( restart )
|
||||||
{
|
{
|
||||||
idStr cmdLine = Sys_GetCmdLine();
|
// DG: Sys_ReLaunch() doesn't need any options anymore
|
||||||
if( cmdLine.Find( "com_skipIntroVideos" ) < 0 )
|
// (the old way would have been unnecessarily painful on POSIX systems)
|
||||||
{
|
Sys_ReLaunch();
|
||||||
cmdLine.Append( " +set com_skipIntroVideos 1" );
|
// DG end
|
||||||
}
|
|
||||||
Sys_ReLaunch( ( void* )cmdLine.c_str(), cmdLine.Length() );
|
|
||||||
}
|
}
|
||||||
return idSWFScriptVar();
|
return idSWFScriptVar();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,13 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
// DG: needed for Sys_ReLaunch()
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
static const char** cmdargv = NULL;
|
||||||
|
static int cmdargc = 0;
|
||||||
|
// DG end
|
||||||
|
|
||||||
#ifdef ID_MCHECK
|
#ifdef ID_MCHECK
|
||||||
#include <mcheck.h>
|
#include <mcheck.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,7 +53,6 @@ static idStr basepath;
|
||||||
static idStr savepath;
|
static idStr savepath;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============
|
==============
|
||||||
Sys_DefaultSavePath
|
Sys_DefaultSavePath
|
||||||
|
@ -645,6 +651,7 @@ Sys_GetCmdLine
|
||||||
*/
|
*/
|
||||||
const char* Sys_GetCmdLine()
|
const char* Sys_GetCmdLine()
|
||||||
{
|
{
|
||||||
|
// DG: don't use this, use cmdargv and cmdargc instead!
|
||||||
return "TODO Sys_GetCmdLine";
|
return "TODO Sys_GetCmdLine";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,9 +660,80 @@ const char* Sys_GetCmdLine()
|
||||||
Sys_ReLaunch
|
Sys_ReLaunch
|
||||||
========================
|
========================
|
||||||
*/
|
*/
|
||||||
void Sys_ReLaunch( void* data, const unsigned int dataSize )
|
void Sys_ReLaunch()
|
||||||
{
|
{
|
||||||
idLib::Error( "Could not start process: TODO Sys_ReLaunch() " );
|
// DG: implementing this... basic old fork() exec() (+ setsid()) routine..
|
||||||
|
// NOTE: this function used to have parameters: the commandline arguments, but as one string..
|
||||||
|
// for Linux/Unix we want one char* per argument so we'll just add the friggin'
|
||||||
|
// " +set com_skipIntroVideos 1" to the other commandline arguments in this function.
|
||||||
|
|
||||||
|
int ret = fork();
|
||||||
|
if( ret < 0 )
|
||||||
|
idLib::Error( "Sys_ReLaunch(): Couldn't fork(), reason: %s ", strerror( errno ) );
|
||||||
|
|
||||||
|
if( ret == 0 )
|
||||||
|
{
|
||||||
|
// child process
|
||||||
|
|
||||||
|
// get our own session so we don't depend on the (soon to be killed)
|
||||||
|
// parent process anymore - else we'll freeze
|
||||||
|
pid_t sId = setsid();
|
||||||
|
if( sId == ( pid_t ) - 1 )
|
||||||
|
{
|
||||||
|
idLib::Error( "Sys_ReLaunch(): setsid() failed! Reason: %s ", strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// close all FDs (except for stdin/out/err) so we don't leak FDs
|
||||||
|
DIR* devfd = opendir( "/dev/fd" );
|
||||||
|
if( devfd != NULL )
|
||||||
|
{
|
||||||
|
struct dirent entry;
|
||||||
|
struct dirent* result;
|
||||||
|
while( readdir_r( devfd, &entry, &result ) == 0 )
|
||||||
|
{
|
||||||
|
const char* filename = result->d_name;
|
||||||
|
char* endptr = NULL;
|
||||||
|
long int fd = strtol( filename, &endptr, 0 );
|
||||||
|
if( endptr != filename && fd > STDERR_FILENO )
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
idLib::Warning( "Sys_ReLaunch(): Couldn't open /dev/fd/ - will leak file descriptors. Reason: %s", strerror( errno ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// + 3 because "+set" "com_skipIntroVideos" "1" - and note that while we'll skip
|
||||||
|
// one (the first) cmdargv argument, we need one more pointer for NULL at the end.
|
||||||
|
int argc = cmdargc + 3;
|
||||||
|
const char** argv = ( const char** )calloc( argc, sizeof( char* ) );
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for( i = 0; i < cmdargc - 1; ++i )
|
||||||
|
argv[i] = cmdargv[i + 1]; // ignore cmdargv[0] == executable name
|
||||||
|
|
||||||
|
// add +set com_skipIntroVideos 1
|
||||||
|
argv[i++] = "+set";
|
||||||
|
argv[i++] = "com_skipIntroVideos";
|
||||||
|
argv[i++] = "1";
|
||||||
|
// execv expects NULL terminated array
|
||||||
|
argv[i] = NULL;
|
||||||
|
|
||||||
|
const char* exepath = Sys_EXEPath();
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
execv( exepath, ( char** )argv );
|
||||||
|
// we only get here if execv() fails, else the executable is restarted
|
||||||
|
idLib::Error( "Sys_ReLaunch(): WTF exec() failed! Reason: %s ", strerror( errno ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// original process
|
||||||
|
// just do a clean shutdown
|
||||||
|
cmdSystem->AppendCommandText( "quit\n" );
|
||||||
|
}
|
||||||
|
// DG end
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -665,6 +743,10 @@ main
|
||||||
*/
|
*/
|
||||||
int main( int argc, const char** argv )
|
int main( int argc, const char** argv )
|
||||||
{
|
{
|
||||||
|
// DG: needed for Sys_ReLaunch()
|
||||||
|
cmdargc = argc;
|
||||||
|
cmdargv = argv;
|
||||||
|
// DG end
|
||||||
#ifdef ID_MCHECK
|
#ifdef ID_MCHECK
|
||||||
// must have -lmcheck linkage
|
// must have -lmcheck linkage
|
||||||
mcheck( abrt_func );
|
mcheck( abrt_func );
|
||||||
|
|
|
@ -432,7 +432,9 @@ void Sys_Init();
|
||||||
void Sys_Shutdown();
|
void Sys_Shutdown();
|
||||||
void Sys_Error( const char* error, ... );
|
void Sys_Error( const char* error, ... );
|
||||||
const char* Sys_GetCmdLine();
|
const char* Sys_GetCmdLine();
|
||||||
void Sys_ReLaunch( void* launchData, unsigned int launchDataSize );
|
// DG: Sys_ReLaunch() doesn't need any options (and the old way is painful for POSIX systems)
|
||||||
|
void Sys_ReLaunch();
|
||||||
|
// DG end
|
||||||
void Sys_Launch( const char* path, idCmdArgs& args, void* launchData, unsigned int launchDataSize );
|
void Sys_Launch( const char* path, idCmdArgs& args, void* launchData, unsigned int launchDataSize );
|
||||||
void Sys_SetLanguageFromSystem();
|
void Sys_SetLanguageFromSystem();
|
||||||
const char* Sys_DefaultLanguage();
|
const char* Sys_DefaultLanguage();
|
||||||
|
|
|
@ -290,7 +290,7 @@ const char * Sys_GetCmdLine() {
|
||||||
Sys_ReLaunch
|
Sys_ReLaunch
|
||||||
========================
|
========================
|
||||||
*/
|
*/
|
||||||
void Sys_ReLaunch( void * data, const unsigned int dataSize ) {
|
void Sys_ReLaunch() {
|
||||||
TCHAR szPathOrig[MAX_PRINT_MSG];
|
TCHAR szPathOrig[MAX_PRINT_MSG];
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
@ -298,7 +298,17 @@ void Sys_ReLaunch( void * data, const unsigned int dataSize ) {
|
||||||
ZeroMemory( &si, sizeof(si) );
|
ZeroMemory( &si, sizeof(si) );
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
strcpy( szPathOrig, va( "\"%s\" %s", Sys_EXEPath(), (const char *)data ) );
|
// DG: we don't have function arguments in Sys_ReLaunch() anymore, everyone only passed
|
||||||
|
// the command-line +" +set com_skipIntroVideos 1" anyway and it was painful on POSIX systems
|
||||||
|
// so let's just add it here.
|
||||||
|
idStr cmdLine = Sys_GetCmdLine();
|
||||||
|
if( cmdLine.Find( "com_skipIntroVideos" ) < 0 )
|
||||||
|
{
|
||||||
|
cmdLine.Append( " +set com_skipIntroVideos 1" );
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy( szPathOrig, va( "\"%s\" %s", Sys_EXEPath(), cmdLine.c_str() ) );
|
||||||
|
// DG end
|
||||||
|
|
||||||
CloseHandle( hProcessMutex );
|
CloseHandle( hProcessMutex );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue