Browse Source

Crashhandler refactoring for POSIX systems. Shows engine version now.

pull/2/head
Alibek Omarov 7 years ago
parent
commit
d9320f964e
  1. 3
      engine/client/gl_local.h
  2. 2
      engine/client/gl_rmain.c
  3. 175
      engine/common/crashhandler.c
  4. 5
      engine/common/sys_con.c

3
engine/client/gl_local.h

@ -235,8 +235,6 @@ extern ref_instance_t RI;
extern ref_globals_t tr; extern ref_globals_t tr;
extern float gldepthmin, gldepthmax; extern float gldepthmin, gldepthmax;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
extern dlight_t cl_dlights[MAX_DLIGHTS]; extern dlight_t cl_dlights[MAX_DLIGHTS];
extern dlight_t cl_elights[MAX_ELIGHTS]; extern dlight_t cl_elights[MAX_ELIGHTS];
#define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities) #define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities)
@ -328,7 +326,6 @@ void R_PushDlights( void );
void R_AnimateLight( void ); void R_AnimateLight( void );
void R_GetLightSpot( vec3_t lightspot ); void R_GetLightSpot( vec3_t lightspot );
void R_MarkLights( dlight_t *light, int bit, mnode_t *node ); void R_MarkLights( dlight_t *light, int bit, mnode_t *node );
void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, qboolean useAmbient, float radius );
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot ); colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot );
int R_CountSurfaceDlights( msurface_t *surf ); int R_CountSurfaceDlights( msurface_t *surf );
colorVec R_LightPoint( const vec3_t p0 ); colorVec R_LightPoint( const vec3_t p0 );

2
engine/client/gl_rmain.c

@ -24,8 +24,6 @@ GNU General Public License for more details.
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA ) #define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
msurface_t *r_debug_surface;
const char *r_debug_hitbox;
float gldepthmin, gldepthmax; float gldepthmin, gldepthmax;
ref_instance_t RI; ref_instance_t RI;

175
engine/common/crashhandler.c

@ -12,6 +12,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#define _GNU_SOURCE
#include "common.h" #include "common.h"
@ -186,7 +187,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
{ {
// save config // save config
if( host.state != HOST_CRASHED ) if( host.status != HOST_CRASHED )
{ {
// check to avoid recursive call // check to avoid recursive call
host.crashed = true; host.crashed = true;
@ -199,7 +200,7 @@ long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
CL_Crashed(); // tell client about crash CL_Crashed(); // tell client about crash
else host.state = HOST_CRASHED; else host.status = HOST_CRASHED;
if( host.developer <= 0 ) if( host.developer <= 0 )
{ {
@ -232,139 +233,187 @@ void Sys_RestoreCrashHandler( void )
#elif XASH_CRASHHANDLER == CRASHHANDLER_UCONTEXT #elif XASH_CRASHHANDLER == CRASHHANDLER_UCONTEXT
// Posix signal handler // Posix signal handler
#include "library.h" #include "library.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined __ANDROID__
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__ANDROID__) || defined(__linux__)
#define HAVE_UCONTEXT_H 1 #define HAVE_UCONTEXT_H 1
#endif #endif
#ifdef HAVE_UCONTEXT_H #ifdef HAVE_UCONTEXT_H
#include <ucontext.h> #include <ucontext.h>
#endif #endif
#include <signal.h>
#include <sys/mman.h> #include <sys/mman.h>
int printframe( char *buf, int len, int i, void *addr ) int printframe( char *buf, int len, int i, void *addr )
{ {
Dl_info dlinfo; Dl_info dlinfo;
if( len <= 0 ) return 0; // overflow if( len <= 0 )
return 0; // overflow
if( dladdr( addr, &dlinfo )) if( dladdr( addr, &dlinfo ))
{ {
if( dlinfo.dli_sname ) if( dlinfo.dli_sname )
return Q_snprintf( buf, len, "% 2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname, return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address (unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
else else
return Q_snprintf( buf, len, "% 2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
} }
else else
return Q_snprintf( buf, len, "% 2d: %p\n", i, addr ); // print only address return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
} }
struct sigaction oldFilter; struct sigaction oldFilter;
#define STACK_BACKTRACE_STR_LEN 17
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR_LEN 12
#define STACK_DUMP_STR "Stack dump:\n"
#define ALIGN( x, y ) (((int) (x) + ((y)-1)) & ~((y)-1))
static void Sys_Crash( int signal, siginfo_t *si, void *context) static void Sys_Crash( int signal, siginfo_t *si, void *context)
{ {
void *trace[32]; void *pc, **bp, **sp; // this must be set for every OS!
char message[8192];
int len, logfd, i = 0;
size_t pagesize;
char message[4096], stackframe[256];
int len, stacklen, logfd, i = 0;
#if defined(__OpenBSD__) #if defined(__OpenBSD__)
struct sigcontext *ucontext = (struct sigcontext*)context; struct sigcontext *ucontext = (struct sigcontext*)context;
#else #else
ucontext_t *ucontext = (ucontext_t*)context; ucontext_t *ucontext = (ucontext_t*)context;
#endif #endif
#if defined(__x86_64__) #if defined(__x86_64__)
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
void *pc = (void*)ucontext->uc_mcontext.mc_rip, **bp = (void**)ucontext->uc_mcontext.mc_rbp, **sp = (void**)ucontext->uc_mcontext.mc_rsp; pc = (void*)ucontext->uc_mcontext.mc_rip;
bp = (void**)ucontext->uc_mcontext.mc_rbp;
sp = (void**)ucontext->uc_mcontext.mc_rsp;
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
void *pc = (void*)ucontext->uc_mcontext.__gregs[REG_RIP], **bp = (void**)ucontext->uc_mcontext.__gregs[REG_RBP], **sp = (void**)ucontext->uc_mcontext.__gregs[REG_RSP]; pc = (void*)ucontext->uc_mcontext.__gregs[REG_RIP];
bp = (void**)ucontext->uc_mcontext.__gregs[REG_RBP];
sp = (void**)ucontext->uc_mcontext.__gregs[REG_RSP];
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
void *pc = (void*)ucontext->sc_rip, **bp = (void**)ucontext->sc_rbp, **sp = (void**)ucontext->sc_rsp; pc = (void*)ucontext->sc_rip;
bp = (void**)ucontext->sc_rbp;
sp = (void**)ucontext->sc_rsp;
#else #else
void *pc = (void*)ucontext->uc_mcontext.gregs[REG_RIP], **bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP], **sp = (void**)ucontext->uc_mcontext.gregs[REG_RSP]; pc = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
sp = (void**)ucontext->uc_mcontext.gregs[REG_RSP];
#endif #endif
#elif defined(__i386__) #elif defined(__i386__)
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
void *pc = (void*)ucontext->uc_mcontext.mc_eip, **bp = (void**)ucontext->uc_mcontext.mc_ebp, **sp = (void**)ucontext->uc_mcontext.mc_esp; pc = (void*)ucontext->uc_mcontext.mc_eip;
bp = (void**)ucontext->uc_mcontext.mc_ebp;
sp = (void**)ucontext->uc_mcontext.mc_esp;
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
void *pc = (void*)ucontext->uc_mcontext.__gregs[REG_EIP], **bp = (void**)ucontext->uc_mcontext.__gregs[REG_EBP], **sp = (void**)ucontext->uc_mcontext.__gregs[REG_ESP]; pc = (void*)ucontext->uc_mcontext.__gregs[REG_EIP];
bp = (void**)ucontext->uc_mcontext.__gregs[REG_EBP];
sp = (void**)ucontext->uc_mcontext.__gregs[REG_ESP];
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
void *pc = (void*)ucontext->sc_eip, **bp = (void**)ucontext->sc_ebp, **sp = (void**)ucontext->sc_esp; pc = (void*)ucontext->sc_eip;
bp = (void**)ucontext->sc_ebp;
sp = (void**)ucontext->sc_esp;
#else #else
void *pc = (void*)ucontext->uc_mcontext.gregs[REG_EIP], **bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP], **sp = (void**)ucontext->uc_mcontext.gregs[REG_ESP]; pc = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
sp = (void**)ucontext->uc_mcontext.gregs[REG_ESP];
#endif #endif
#elif defined(__aarch64__) // arm not tested #elif defined(__aarch64__) // arm not tested
void *pc = (void*)ucontext->uc_mcontext.pc, **bp = (void*)ucontext->uc_mcontext.regs[29], **sp = (void*)ucontext->uc_mcontext.sp; pc = (void*)ucontext->uc_mcontext.pc;
bp = (void*)ucontext->uc_mcontext.regs[29];
sp = (void*)ucontext->uc_mcontext.sp;
#elif defined(__arm__) #elif defined(__arm__)
void *pc = (void*)ucontext->uc_mcontext.arm_pc, **bp = (void*)ucontext->uc_mcontext.arm_fp, **sp = (void*)ucontext->uc_mcontext.arm_sp; pc = (void*)ucontext->uc_mcontext.arm_pc;
bp = (void*)ucontext->uc_mcontext.arm_fp;
sp = (void*)ucontext->uc_mcontext.arm_sp;
#else #else
#error "Unknown arch!!!" #error "Unknown arch!!!"
#endif #endif
// Safe actions first, stack and memory may be corrupted
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) // safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, 4096, "Sys_Crash: signal %d, err %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr ); len = Q_snprintf( message, sizeof( message ), "Ver: %s %s (build %i-%s, %s-%s)\n",
#else XASH_ENGINE_NAME, XASH_VERSION, Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
len = Q_snprintf( message, 4096, "Sys_Crash: signal %d, err %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#endif #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
write(2, message, len); 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 );
// Flush buffers before writing directly to descriptors #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( 2, message, len );
// flush buffers before writing directly to descriptors
fflush( stdout ); fflush( stdout );
fflush( stderr ); fflush( stderr );
// Now get log fd and write trace directly to log
// now get log fd and write trace directly to log
logfd = Sys_LogFileNo(); logfd = Sys_LogFileNo();
write( logfd, message, len ); write( logfd, message, len );
write( 2, "Stack backtrace:\n", 17 );
write( logfd, "Stack backtrace:\n", 17 ); // try to print backtrace
strncpy(message + len, "Stack backtrace:\n", 4096 - len); write( 2, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
len += 17; write( logfd, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
size_t pagesize = sysconf(_SC_PAGESIZE); strncpy( message + len, STACK_BACKTRACE_STR, sizeof( message ) - len );
len += STACK_BACKTRACE_STR_LEN;
pagesize = sysconf( _SC_PAGESIZE );
do do
{ {
int line = printframe( message + len, 4096 - len, ++i, pc); int line = printframe( message + len, sizeof( message ) - len, ++i, pc);
write( 2, message + len, line ); write( 2, message + len, line );
write( logfd, message + len, line ); write( logfd, message + len, line );
len += line; len += line;
//if( !dladdr(bp,0) ) break; // Only when bp is in module //if( !dladdr(bp,0) ) break; // only when bp is in module
if( ( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) && if( ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) &&
( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_EXEC ) == -1) && ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ | PROT_EXEC ) == -1) &&
( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE ) == -1) && ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ | PROT_WRITE ) == -1) &&
( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ ) == -1) ) ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ ) == -1) )
break; break;
if( ( mprotect((char *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) && if( ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) &&
( mprotect((char *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_EXEC ) == -1) && ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ | PROT_EXEC ) == -1) &&
( mprotect((char *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE ) == -1) && ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ | PROT_WRITE ) == -1) &&
( mprotect((char *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ ) == -1) ) ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ ) == -1) )
break; break;
pc = bp[1]; pc = bp[1];
bp = (void**)bp[0]; bp = (void**)bp[0];
} }
while( bp && i < 128 ); while( bp && i < 128 );
// Try to print stack
write( 2, "Stack dump:\n", 12 ); // try to print stack
write( logfd, "Stack dump:\n", 12 ); write( 2, STACK_DUMP_STR, STACK_DUMP_STR_LEN );
strncpy( message + len, "Stack dump:\n", 4096 - len ); write( logfd, STACK_DUMP_STR, STACK_DUMP_STR_LEN );
strncpy( message + len, STACK_DUMP_STR, sizeof( message ) - len );
len += 12; len += STACK_DUMP_STR_LEN;
if( ( mprotect((char *)(((int) sp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) != -1) ||
( mprotect((char *)(((int) sp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_EXEC ) != -1) || if( ( mprotect((char *)ALIGN( sp, pagesize ), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) != -1) ||
( mprotect((char *)(((int) sp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE ) != -1) || ( mprotect((char *)ALIGN( sp, pagesize ), pagesize, PROT_READ | PROT_EXEC ) != -1) ||
( mprotect((char *)(((int) sp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ ) != -1) ) ( mprotect((char *)ALIGN( sp, pagesize ), pagesize, PROT_READ | PROT_WRITE ) != -1) ||
( mprotect((char *)ALIGN( sp, pagesize ), pagesize, PROT_READ ) != -1) )
{
for( i = 0; i < 32; i++ ) for( i = 0; i < 32; i++ )
{ {
int line = printframe( message + len, 4096 - len, i, sp[i] ); int line = printframe( message + len, sizeof( message ) - len, i, sp[i] );
write( 2, message + len, line ); write( 2, message + len, line );
write( logfd, message + len, line ); write( logfd, message + len, line );
len += line; len += line;
} }
// Put MessageBox as Sys_Error }
// put MessageBox as Sys_Error
Msg( "%s\n", message ); Msg( "%s\n", message );
#ifdef XASH_SDL #ifdef XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif #endif
MSGBOX( message ); MSGBOX( message );
// Log saved, now we can try to save configs and close log correctly, it may crash // log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
CL_Crashed(); CL_Crashed();
host.state = HOST_CRASHED; host.status = HOST_CRASHED;
host.crashed = true; host.crashed = true;
Sys_Quit(); Sys_Quit();
@ -375,10 +424,10 @@ void Sys_SetupCrashHandler( void )
struct sigaction act; struct sigaction act;
act.sa_sigaction = Sys_Crash; act.sa_sigaction = Sys_Crash;
act.sa_flags = SA_SIGINFO | SA_ONSTACK; act.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigaction(SIGSEGV, &act, &oldFilter); sigaction( SIGSEGV, &act, &oldFilter );
sigaction(SIGABRT, &act, &oldFilter); sigaction( SIGABRT, &act, &oldFilter );
sigaction(SIGBUS, &act, &oldFilter); sigaction( SIGBUS, &act, &oldFilter );
sigaction(SIGILL, &act, &oldFilter); sigaction( SIGILL, &act, &oldFilter );
} }
void Sys_RestoreCrashHandler( void ) void Sys_RestoreCrashHandler( void )

5
engine/common/sys_con.c

@ -90,6 +90,11 @@ SYSTEM LOG
=============================================================================== ===============================================================================
*/ */
int Sys_LogFileNo( void )
{
return s_ld.logfileno;
}
void Sys_InitLog( void ) void Sys_InitLog( void )
{ {
const char *mode; const char *mode;

Loading…
Cancel
Save