diff --git a/engine/platform/posix/crash_posix.c b/engine/platform/posix/crash_posix.c index 089ad111..9461b452 100644 --- a/engine/platform/posix/crash_posix.c +++ b/engine/platform/posix/crash_posix.c @@ -18,20 +18,26 @@ GNU General Public License for more details. #if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE #include #include +#if XASH_ANDROID +#include +#include +#include +#endif #include "library.h" #include "input.h" #include "crash.h" +#if XASH_ANDROID +static char crashlog_path[MAX_OSPATH]; +#endif + static qboolean have_libbacktrace = false; static char crash_message[8192]; static void Sys_Crash( int signal, siginfo_t *si, void *context ) { - int len, logfd, i = 0; - qboolean detailed_message = false; - // safe actions first, stack and memory may be corrupted - len = Q_snprintf( crash_message, sizeof( crash_message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n", + int len = Q_snprintf( crash_message, sizeof( crash_message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() ); #if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE @@ -42,12 +48,17 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context ) write( STDERR_FILENO, crash_message, len ); +#if XASH_ANDROID + __android_log_write( ANDROID_LOG_FATAL, "Xash", crash_message ); +#endif + // now get log fd and write trace directly to log - logfd = Sys_LogFileNo(); + int logfd = Sys_LogFileNo(); if( logfd >= 0 ) write( logfd, crash_message, len ); #if HAVE_LIBBACKTRACE + qboolean detailed_message = false; if( have_libbacktrace && !detailed_message ) { len = Sys_CrashDetailsLibbacktrace( logfd, crash_message, len, sizeof( crash_message )); @@ -55,6 +66,21 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context ) } #endif // HAVE_LIBBACKTRACE +#if XASH_ANDROID + // also write to a dedicated crash report file the Java side picks up on next launch + if( crashlog_path[0] ) + { + int crashfd = open( crashlog_path, O_WRONLY|O_CREAT|O_TRUNC, 0644 ); + if( crashfd >= 0 ) + { + write( crashfd, crash_message, len ); + close( crashfd ); + } + } + + // JNI/SDL calls aren't safe from a signal handler on Android + _exit( 128 + signal ); +#else #if !XASH_DEDICATED IN_SetMouseGrab( false ); #endif @@ -68,6 +94,7 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context ) CL_Crashed(); Sys_Quit( "crashed" ); +#endif // XASH_ANDROID } static struct sigaction old_segv_act; @@ -83,6 +110,22 @@ void Sys_SetupCrashHandler( const char *argv0 ) .sa_flags = SA_SIGINFO | SA_ONSTACK, }; +#if XASH_ANDROID + const char *crashdir = getenv( "XASH3D_CRASH_DIR" ); + + if( !COM_StringEmptyOrNULL( crashdir )) + Q_snprintf( crashlog_path, sizeof( crashlog_path ), "%s/crash.log", crashdir ); + + // unblock the engine/SDL_main thread just in case + sigset_t set; + sigemptyset( &set ); + sigaddset( &set, SIGSEGV ); + sigaddset( &set, SIGABRT ); + sigaddset( &set, SIGBUS ); + sigaddset( &set, SIGILL ); + pthread_sigmask( SIG_UNBLOCK, &set, NULL ); +#endif + #if HAVE_LIBBACKTRACE have_libbacktrace = Sys_SetupLibbacktrace( argv0 ); #endif // HAVE_LIBBACKTRACE @@ -91,7 +134,6 @@ void Sys_SetupCrashHandler( const char *argv0 ) sigaction( SIGABRT, &act, &old_abrt_act ); sigaction( SIGBUS, &act, &old_bus_act ); sigaction( SIGILL, &act, &old_ill_act ); - } void Sys_RestoreCrashHandler( void )