engine: platform: posix: use glibc-based backtrace implementation for crash handling, if execinfo.h can be found
This commit is contained in:
parent
c3ebb84b97
commit
d0464ef602
3 changed files with 92 additions and 3 deletions
82
engine/platform/posix/crash_glibc.c
Normal file
82
engine/platform/posix/crash_glibc.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
crashhandler.c - advanced crashhandler
|
||||
Copyright (C) 2016 Mittorn
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
// on Glibc (which potentially might not be only Linux) systems we
|
||||
// have backtrace() and backtrace_symbols() calls, which replace for us
|
||||
// platform-specific code
|
||||
#if HAVE_EXECINFO
|
||||
#include "common.h"
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
{
|
||||
char message[8192];
|
||||
int len, logfd, i = 0;
|
||||
int size;
|
||||
void *addrs[16];
|
||||
char **syms;
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
#else
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
|
||||
#endif
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
|
||||
size = backtrace( addrs, sizeof( addrs ) / sizeof( addrs[0] ));
|
||||
syms = backtrace_symbols( addrs, size );
|
||||
|
||||
for( i = 0; i < size && syms; i++ )
|
||||
{
|
||||
size_t symlen = Q_strlen( syms[i] );
|
||||
char ch = '\n';
|
||||
|
||||
write( logfd, syms[i], symlen );
|
||||
write( logfd, &ch, 1 );
|
||||
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "%2d: %s\n", i, syms[i] );
|
||||
}
|
||||
|
||||
// put MessageBox as Sys_Error
|
||||
Msg( "%s\n", message );
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
host.crashed = true;
|
||||
Platform_MessageBox( "Xash Error", message, false );
|
||||
|
||||
// log saved, now we can try to save configs and close log correctly, it may crash
|
||||
if( host.type == HOST_NORMAL )
|
||||
CL_Crashed();
|
||||
host.status = HOST_CRASHED;
|
||||
|
||||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
#endif // HAVE_EXECINFO
|
|
@ -26,6 +26,11 @@ GNU General Public License for more details.
|
|||
#include <sys/mman.h>
|
||||
#include "library.h"
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context );
|
||||
static struct sigaction oldFilter;
|
||||
|
||||
#if !HAVE_EXECINFO
|
||||
|
||||
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
|
||||
#define STACK_DUMP_STR "Stack dump:\n"
|
||||
|
||||
|
@ -33,8 +38,6 @@ GNU General Public License for more details.
|
|||
#define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 )
|
||||
#define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 ))
|
||||
|
||||
static struct sigaction oldFilter;
|
||||
|
||||
static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
|
||||
{
|
||||
Dl_info dlinfo;
|
||||
|
@ -53,7 +56,7 @@ static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
|
|||
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
|
||||
}
|
||||
|
||||
static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
{
|
||||
void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS!
|
||||
char message[8192];
|
||||
|
@ -200,6 +203,8 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
|||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
#endif // !HAVE_EXECINFO
|
||||
|
||||
void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
struct sigaction act = { 0 };
|
||||
|
|
|
@ -111,6 +111,8 @@ def configure(conf):
|
|||
if hasattr(conf.options, 'DLLEMU'):
|
||||
conf.define_cond('XASH_DLL_LOADER', conf.options.DLLEMU)
|
||||
|
||||
conf.check_cc(header_name='execinfo.h', mandatory=False, define_name='HAVE_EXECINFO')
|
||||
|
||||
conf.define('ENGINE_DLL', 1)
|
||||
conf.define_cond('XASH_ENGINE_TESTS', conf.options.ENGINE_TESTS)
|
||||
conf.define_cond('XASH_STATIC_LIBS', conf.env.STATIC_LINKING)
|
||||
|
|
Loading…
Add table
Reference in a new issue