Skip to content

Commit

Permalink
engine: platform: posix: use glibc-based backtrace implementation for…
Browse files Browse the repository at this point in the history
… crash handling, if execinfo.h can be found
  • Loading branch information
a1batross committed Feb 2, 2025
1 parent c3ebb84 commit d0464ef
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 3 deletions.
82 changes: 82 additions & 0 deletions engine/platform/posix/crash_glibc.c
Original file line number Diff line number Diff line change
@@ -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
11 changes: 8 additions & 3 deletions engine/platform/posix/crash_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@ 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"

#define STACK_BACKTRACE_STR_LEN ( sizeof( STACK_BACKTRACE_STR ) - 1 )
#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;
Expand All @@ -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];
Expand Down Expand Up @@ -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 };
Expand Down
2 changes: 2 additions & 0 deletions engine/wscript
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit d0464ef

Please sign in to comment.