From 4091e0cfaaf3dcb1fbd1429903d75d42166f6acd Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 20 Mar 2004 21:36:10 +0000 Subject: [PATCH] ForceCrashHandlerDeadlock --- stepmania/src/archutils/Unix/CrashHandler.cpp | 61 +++++++++++++------ stepmania/src/archutils/Unix/CrashHandler.h | 2 + .../src/archutils/Unix/CrashHandlerChild.cpp | 27 ++++---- .../src/archutils/Unix/CrashHandlerInternal.h | 10 +-- 4 files changed, 63 insertions(+), 37 deletions(-) diff --git a/stepmania/src/archutils/Unix/CrashHandler.cpp b/stepmania/src/archutils/Unix/CrashHandler.cpp index c5d7eb5671..7ac96f539e 100644 --- a/stepmania/src/archutils/Unix/CrashHandler.cpp +++ b/stepmania/src/archutils/Unix/CrashHandler.cpp @@ -81,27 +81,24 @@ static void parent_write(int to_child, const void *p, size_t size) } } -static void parent_process( int to_child, const void **BacktracePointers, const CrashData *crash ) +static void parent_process( int to_child, const CrashData *crash ) { - /* 1. Write the backtrace pointers. */ - parent_write(to_child, BacktracePointers, sizeof(void *)*BACKTRACE_MAX_SIZE); - - /* 2. Write the CrashData. */ + /* 1. Write the CrashData. */ parent_write(to_child, crash, sizeof(CrashData)); - /* 3. Write info. */ + /* 2. Write info. */ const char *p = RageLog::GetInfo(); int size = strlen(p)+1; parent_write(to_child, &size, sizeof(size)); parent_write(to_child, p, size); - /* 4. Write AdditionalLog. */ + /* 3. Write AdditionalLog. */ p = RageLog::GetAdditionalLog(); size = strlen(p)+1; parent_write(to_child, &size, sizeof(size)); parent_write(to_child, p, size); - /* 5. Write RecentLogs. */ + /* 4. Write RecentLogs. */ int cnt = 0; const char *ps[1024]; while( cnt < 1024 && (ps[cnt] = RageLog::GetRecentLog( cnt )) != NULL ) @@ -115,13 +112,13 @@ static void parent_process( int to_child, const void **BacktracePointers, const parent_write(to_child, ps[i], size); } - /* 6. Write CHECKPOINTs. */ + /* 5. Write CHECKPOINTs. */ p = Checkpoints::GetLogs("\n"); size = strlen(p)+1; parent_write(to_child, &size, sizeof(size)); parent_write(to_child, p, size); - /* 7. Write the crashed thread's name. */ + /* 6. Write the crashed thread's name. */ p = RageThread::GetCurThreadName(); size = strlen(p)+1; parent_write(to_child, &size, sizeof(size)); @@ -290,13 +287,6 @@ static void RunCrashHandler( const CrashData *crash ) * tends to do more harm than good. Let's just try to get the crashdump written quickly. */ // RageThread::HaltAllThreads(); - /* Do this early, so functions called below don't end up on the backtrace. */ - const void *BacktracePointers[BACKTRACE_MAX_SIZE]; - if( crash->type == CrashData::FORCE_CRASH_THIS_THREAD ) - GetBacktrace( BacktracePointers, BACKTRACE_MAX_SIZE, NULL ); - else - GetBacktrace( BacktracePointers, BACKTRACE_MAX_SIZE, &crash->ctx ); - /* We need to be very careful, since we're under crash conditions. Let's fork * a process and exec ourself to get a clean environment to work in. */ int fds[2]; @@ -321,7 +311,7 @@ static void RunCrashHandler( const CrashData *crash ) else { close(fds[0]); - parent_process( fds[1], BacktracePointers, crash ); + parent_process( fds[1], crash ); int status = 0; waitpid( childpid, &status, 0 ); if( WIFSIGNALED(status) ) @@ -332,22 +322,48 @@ static void RunCrashHandler( const CrashData *crash ) void ForceCrashHandler( const char *reason ) { CrashData crash; + memset( &crash, 0, sizeof(crash) ); + crash.type = CrashData::FORCE_CRASH_THIS_THREAD; strncpy( crash.reason, reason, sizeof(crash.reason) ); crash.reason[ sizeof(crash.reason)-1 ] = 0; + GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, NULL ); + RunCrashHandler( &crash ); } +void ForceCrashHandlerDeadlock( const char *reason, const BacktraceContext *ctx ) +{ + CrashData crash; + memset( &crash, 0, sizeof(crash) ); + + crash.type = CrashData::FORCE_CRASH_DEADLOCK; + strncpy( crash.reason, reason, sizeof(crash.reason) ); + crash.reason[ sizeof(crash.reason)-1 ] = 0; + + GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, NULL ); + GetBacktrace( crash.BacktracePointers2, BACKTRACE_MAX_SIZE, ctx ); + + RunCrashHandler( &crash ); +} + +/* XXX test for recursive crashes here (eg. GetBacktrace crashing) */ + #if !defined(DARWIN) void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc ) { CrashData crash; + memset( &crash, 0, sizeof(crash) ); + crash.type = CrashData::SIGNAL; crash.signal = signal; crash.si = *si; - GetSignalBacktraceContext( &crash.ctx, uc ); + BacktraceContext ctx; + GetSignalBacktraceContext( &ctx, uc ); + GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, &ctx ); + RunCrashHandler( &crash ); } #endif @@ -356,10 +372,15 @@ void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc ) OSStatus CrashExceptionHandler( ExceptionInformation *e ) { CrashData crash; + memset( &crash, 0, sizeof(crash) ); + crash.type = CrashData::OSX_EXCEPTION; crash.kind = e->theKind; - GetExceptionBacktraceContext( &crash.ctx, e ); + BacktraceContext ctx; + GetExceptionBacktraceContext( &ctx, e ); + GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, &ctx ); + RunCrashHandler( &crash ); return -1; } diff --git a/stepmania/src/archutils/Unix/CrashHandler.h b/stepmania/src/archutils/Unix/CrashHandler.h index 1d4c6ef2b6..cbdf84a416 100644 --- a/stepmania/src/archutils/Unix/CrashHandler.h +++ b/stepmania/src/archutils/Unix/CrashHandler.h @@ -2,6 +2,8 @@ #define CRASH_HANDLER_H void ForceCrashHandler( const char *reason ); +struct BacktraceContext; +void ForceCrashHandlerDeadlock( const char *reason, const BacktraceContext *ctx ); void CrashHandlerHandleArgs( int argc, char* argv[] ); void InitializeCrashHandler(); diff --git a/stepmania/src/archutils/Unix/CrashHandlerChild.cpp b/stepmania/src/archutils/Unix/CrashHandlerChild.cpp index b8e72d3abd..1d7410348b 100644 --- a/stepmania/src/archutils/Unix/CrashHandlerChild.cpp +++ b/stepmania/src/archutils/Unix/CrashHandlerChild.cpp @@ -27,7 +27,7 @@ extern const unsigned version_num; const char *g_pCrashHandlerArgv0 = NULL; -static void output_stack_trace( FILE *out, void **BacktracePointers ) +static void output_stack_trace( FILE *out, const void **BacktracePointers ) { if( BacktracePointers[0] == BACKTRACE_METHOD_NOT_AVAILABLE ) { @@ -164,26 +164,22 @@ static void child_process() { int ret; - /* 1. Read the backtrace pointers. */ - void *BacktracePointers[BACKTRACE_MAX_SIZE]; - ret = read(3, BacktracePointers, sizeof(void *)*BACKTRACE_MAX_SIZE); - - /* 2. Read the CrashData. */ + /* 1. Read the CrashData. */ CrashData crash; ret = read(3, &crash, sizeof(CrashData)); - /* 3. Read info. */ + /* 2. Read info. */ int size; ret = read(3, &size, sizeof(size)); char *Info = new char [size]; ret = read(3, Info, size); - /* 4. Read AdditionalLog. */ + /* 3. Read AdditionalLog. */ ret = read(3, &size, sizeof(size)); char *AdditionalLog = new char [size]; ret = read(3, AdditionalLog, size); - /* 5. Read RecentLogs. */ + /* 4. Read RecentLogs. */ int cnt = 0; ret = read(3, &cnt, sizeof(cnt)); char *Recent[1024]; @@ -194,7 +190,7 @@ static void child_process() ret = read(3, Recent[i], size); } - /* 6. Read CHECKPOINTs. */ + /* 5. Read CHECKPOINTs. */ ret = read(3, &size, sizeof(size)); char *temp = new char [size]; ret = read(3, temp, size); @@ -202,7 +198,7 @@ static void child_process() split(temp, "$$", Checkpoints); delete [] temp; - /* 7. Read the crashed thread's name. */ + /* 6. Read the crashed thread's name. */ ret = read(3, &size, sizeof(size)); temp = new char [size]; ret = read(3, temp, size); @@ -270,6 +266,7 @@ static void child_process() #endif case CrashData::FORCE_CRASH_THIS_THREAD: + case CrashData::FORCE_CRASH_DEADLOCK: crash.reason[ sizeof(crash.reason)-1] = 0; reason = crash.reason; break; @@ -283,8 +280,14 @@ static void child_process() fprintf(CrashDump, Checkpoints[i]); fprintf(CrashDump, "\n"); - output_stack_trace( CrashDump, BacktracePointers ); + output_stack_trace( CrashDump, crash.BacktracePointers ); fprintf(CrashDump, "\n"); + if( crash.type == CrashData::FORCE_CRASH_DEADLOCK ) + { + fprintf(CrashDump, "Deadlocked with:\n"); + output_stack_trace( CrashDump, crash.BacktracePointers2 ); + fprintf(CrashDump, "\n"); + } fprintf(CrashDump, "Static log:\n"); fprintf(CrashDump, "%s", Info); diff --git a/stepmania/src/archutils/Unix/CrashHandlerInternal.h b/stepmania/src/archutils/Unix/CrashHandlerInternal.h index 72daf38d1e..3539263d41 100644 --- a/stepmania/src/archutils/Unix/CrashHandlerInternal.h +++ b/stepmania/src/archutils/Unix/CrashHandlerInternal.h @@ -2,6 +2,7 @@ #define CRASH_HANDLER_INTERNAL_H #include "Backtrace.h" +#define BACKTRACE_MAX_SIZE 1024 struct CrashData { @@ -19,14 +20,14 @@ struct CrashData FORCE_CRASH_THIS_THREAD, /* Deadlock detected; give a stack trace for two threads. */ - // FORCE_CRASH_DEADLOCK + FORCE_CRASH_DEADLOCK } type; /* Everything except FORCE_CRASH_THIS_THREAD: */ - BacktraceContext ctx; + const void *BacktracePointers[BACKTRACE_MAX_SIZE]; /* FORCE_CRASH_DEADLOCK only: */ - // BacktraceContext ctx2; + const void *BacktracePointers2[BACKTRACE_MAX_SIZE]; /* SIGNAL only: */ int signal; @@ -35,11 +36,10 @@ struct CrashData /* OSX_EXCEPTION only: */ int kind; - /* FORCE_CRASH_THIS_THREAD only: */ + /* FORCE_CRASH_THIS_THREAD and FORCE_CRASH_DEADLOCK only: */ char reason[256]; }; -#define BACKTRACE_MAX_SIZE 1024 #define CHILD_MAGIC_PARAMETER "--private-do-crash-handler" const char *SignalName( int signo );