From d9320f964edef63cd3db6ad532b3c380ecbf9c51 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 14 May 2018 10:14:41 +0300 Subject: [PATCH] Crashhandler refactoring for POSIX systems. Shows engine version now. --- engine/client/gl_local.h | 3 - engine/client/gl_rmain.c | 4 +- engine/client/gl_rsurf.c | 2 +- engine/common/crashhandler.c | 179 ++++++++++++++++++++++------------- engine/common/sys_con.c | 5 + 5 files changed, 121 insertions(+), 72 deletions(-) diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index 41119e89..b290a71d 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -235,8 +235,6 @@ extern ref_instance_t RI; extern ref_globals_t tr; 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_elights[MAX_ELIGHTS]; #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_GetLightSpot( vec3_t lightspot ); 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 ); int R_CountSurfaceDlights( msurface_t *surf ); colorVec R_LightPoint( const vec3_t p0 ); diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index ac816760..796d4e8b 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -24,9 +24,7 @@ GNU General Public License for more details. #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; static int R_RankForRenderMode( int rendermode ) diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index da2576ec..190aae7c 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -208,7 +208,7 @@ void GL_SetupFogColorForSurfaces( void ) return; if( RI.currententity && RI.currententity->curstate.rendermode == kRenderTransTexture ) - { + { pglFogfv( GL_FOG_COLOR, RI.fogColor ); return; } diff --git a/engine/common/crashhandler.c b/engine/common/crashhandler.c index 9ee66781..5ce4b938 100644 --- a/engine/common/crashhandler.c +++ b/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 GNU General Public License for more details. */ +#define _GNU_SOURCE #include "common.h" @@ -186,7 +187,7 @@ LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) { // save config - if( host.state != HOST_CRASHED ) + if( host.status != HOST_CRASHED ) { // check to avoid recursive call host.crashed = true; @@ -199,7 +200,7 @@ long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) if( host.type == HOST_NORMAL ) CL_Crashed(); // tell client about crash - else host.state = HOST_CRASHED; + else host.status = HOST_CRASHED; if( host.developer <= 0 ) { @@ -232,139 +233,187 @@ void Sys_RestoreCrashHandler( void ) #elif XASH_CRASHHANDLER == CRASHHANDLER_UCONTEXT // Posix signal handler + #include "library.h" -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined __ANDROID__ + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__ANDROID__) || defined(__linux__) #define HAVE_UCONTEXT_H 1 #endif #ifdef HAVE_UCONTEXT_H #include #endif +#include #include int printframe( char *buf, int len, int i, void *addr ) { Dl_info dlinfo; - if( len <= 0 ) return 0; // overflow + if( len <= 0 ) + return 0; // overflow + if( dladdr( addr, &dlinfo )) { 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 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 - 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; +#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) { - 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__) struct sigcontext *ucontext = (struct sigcontext*)context; #else ucontext_t *ucontext = (ucontext_t*)context; #endif + #if defined(__x86_64__) #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__) - 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__) - 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 - 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 #elif defined(__i386__) #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__) - 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__) - 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 - 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 #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__) - 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 -#error "Unknown arch!!!" + #error "Unknown arch!!!" #endif - // Safe actions first, stack and memory may be corrupted - #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - 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 ); - #else - 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 - write(2, message, len); - // Flush buffers before writing directly to descriptors + + // safe actions first, stack and memory may be corrupted + len = Q_snprintf( message, sizeof( message ), "Ver: %s %s (build %i-%s, %s-%s)\n", + XASH_ENGINE_NAME, XASH_VERSION, Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() ); + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__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( 2, message, len ); + + // flush buffers before writing directly to descriptors fflush( stdout ); 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(); write( logfd, message, len ); - write( 2, "Stack backtrace:\n", 17 ); - write( logfd, "Stack backtrace:\n", 17 ); - strncpy(message + len, "Stack backtrace:\n", 4096 - len); - len += 17; - size_t pagesize = sysconf(_SC_PAGESIZE); + + // try to print backtrace + write( 2, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); + write( logfd, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); + strncpy( message + len, STACK_BACKTRACE_STR, sizeof( message ) - len ); + len += STACK_BACKTRACE_STR_LEN; + + pagesize = sysconf( _SC_PAGESIZE ); + 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( logfd, message + len, line ); len += line; - //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) && - ( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_EXEC ) == -1) && - ( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE ) == -1) && - ( mprotect((char *)(((int) bp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ ) == -1) ) + //if( !dladdr(bp,0) ) break; // only when bp is in module + if( ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) && + ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ | PROT_EXEC ) == -1) && + ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ | PROT_WRITE ) == -1) && + ( mprotect( (char *)ALIGN( bp, pagesize ), pagesize, PROT_READ ) == -1) ) break; - if( ( mprotect((char *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), 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 *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE ) == -1) && - ( mprotect((char *)(((int) bp[0] + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ ) == -1) ) + if( ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) && + ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ | PROT_EXEC ) == -1) && + ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ | PROT_WRITE ) == -1) && + ( mprotect( (char *)ALIGN( bp[0], pagesize ), pagesize, PROT_READ ) == -1) ) break; pc = bp[1]; bp = (void**)bp[0]; } while( bp && i < 128 ); - // Try to print stack - write( 2, "Stack dump:\n", 12 ); - write( logfd, "Stack dump:\n", 12 ); - strncpy( message + len, "Stack dump:\n", 4096 - len ); - - len += 12; - 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) || - ( mprotect((char *)(((int) sp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ | PROT_WRITE ) != -1) || - ( mprotect((char *)(((int) sp + (pagesize-1)) & ~(pagesize-1)), pagesize, PROT_READ ) != -1) ) + + // try to print stack + write( 2, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); + write( logfd, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); + strncpy( message + len, STACK_DUMP_STR, sizeof( message ) - len ); + len += STACK_DUMP_STR_LEN; + + if( ( mprotect((char *)ALIGN( sp, pagesize ), pagesize, PROT_READ | PROT_WRITE | PROT_EXEC ) != -1) || + ( mprotect((char *)ALIGN( sp, pagesize ), pagesize, PROT_READ | PROT_EXEC ) != -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++ ) { - 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( logfd, message + len, line ); len += line; } - // Put MessageBox as Sys_Error + } + + // put MessageBox as Sys_Error Msg( "%s\n", message ); #ifdef XASH_SDL SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); #endif 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 ) CL_Crashed(); - host.state = HOST_CRASHED; + host.status = HOST_CRASHED; host.crashed = true; Sys_Quit(); @@ -375,18 +424,18 @@ void Sys_SetupCrashHandler( void ) struct sigaction act; act.sa_sigaction = Sys_Crash; act.sa_flags = SA_SIGINFO | SA_ONSTACK; - sigaction(SIGSEGV, &act, &oldFilter); - sigaction(SIGABRT, &act, &oldFilter); - sigaction(SIGBUS, &act, &oldFilter); - sigaction(SIGILL, &act, &oldFilter); + sigaction( SIGSEGV, &act, &oldFilter ); + sigaction( SIGABRT, &act, &oldFilter ); + sigaction( SIGBUS, &act, &oldFilter ); + sigaction( SIGILL, &act, &oldFilter ); } void Sys_RestoreCrashHandler( void ) { sigaction( SIGSEGV, &oldFilter, NULL ); sigaction( SIGABRT, &oldFilter, NULL ); - sigaction( SIGBUS, &oldFilter, NULL ); - sigaction( SIGILL, &oldFilter, NULL ); + sigaction( SIGBUS, &oldFilter, NULL ); + sigaction( SIGILL, &oldFilter, NULL ); } #elif XASH_CRASHHANDLER == CRASHHANDLER_NULL diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index 409f8934..b6174c78 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -90,6 +90,11 @@ SYSTEM LOG =============================================================================== */ +int Sys_LogFileNo( void ) +{ + return s_ld.logfileno; +} + void Sys_InitLog( void ) { const char *mode;