ForceCrashHandlerDeadlock

This commit is contained in:
Glenn Maynard
2004-03-20 21:36:10 +00:00
parent e8cd1a3709
commit 4091e0cfaa
4 changed files with 63 additions and 37 deletions
+41 -20
View File
@@ -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. */ /* 1. Write the CrashData. */
parent_write(to_child, BacktracePointers, sizeof(void *)*BACKTRACE_MAX_SIZE);
/* 2. Write the CrashData. */
parent_write(to_child, crash, sizeof(CrashData)); parent_write(to_child, crash, sizeof(CrashData));
/* 3. Write info. */ /* 2. Write info. */
const char *p = RageLog::GetInfo(); const char *p = RageLog::GetInfo();
int size = strlen(p)+1; int size = strlen(p)+1;
parent_write(to_child, &size, sizeof(size)); parent_write(to_child, &size, sizeof(size));
parent_write(to_child, p, size); parent_write(to_child, p, size);
/* 4. Write AdditionalLog. */ /* 3. Write AdditionalLog. */
p = RageLog::GetAdditionalLog(); p = RageLog::GetAdditionalLog();
size = strlen(p)+1; size = strlen(p)+1;
parent_write(to_child, &size, sizeof(size)); parent_write(to_child, &size, sizeof(size));
parent_write(to_child, p, size); parent_write(to_child, p, size);
/* 5. Write RecentLogs. */ /* 4. Write RecentLogs. */
int cnt = 0; int cnt = 0;
const char *ps[1024]; const char *ps[1024];
while( cnt < 1024 && (ps[cnt] = RageLog::GetRecentLog( cnt )) != NULL ) 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); parent_write(to_child, ps[i], size);
} }
/* 6. Write CHECKPOINTs. */ /* 5. Write CHECKPOINTs. */
p = Checkpoints::GetLogs("\n"); p = Checkpoints::GetLogs("\n");
size = strlen(p)+1; size = strlen(p)+1;
parent_write(to_child, &size, sizeof(size)); parent_write(to_child, &size, sizeof(size));
parent_write(to_child, p, size); parent_write(to_child, p, size);
/* 7. Write the crashed thread's name. */ /* 6. Write the crashed thread's name. */
p = RageThread::GetCurThreadName(); p = RageThread::GetCurThreadName();
size = strlen(p)+1; size = strlen(p)+1;
parent_write(to_child, &size, sizeof(size)); 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. */ * tends to do more harm than good. Let's just try to get the crashdump written quickly. */
// RageThread::HaltAllThreads(); // 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 /* 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. */ * a process and exec ourself to get a clean environment to work in. */
int fds[2]; int fds[2];
@@ -321,7 +311,7 @@ static void RunCrashHandler( const CrashData *crash )
else else
{ {
close(fds[0]); close(fds[0]);
parent_process( fds[1], BacktracePointers, crash ); parent_process( fds[1], crash );
int status = 0; int status = 0;
waitpid( childpid, &status, 0 ); waitpid( childpid, &status, 0 );
if( WIFSIGNALED(status) ) if( WIFSIGNALED(status) )
@@ -332,22 +322,48 @@ static void RunCrashHandler( const CrashData *crash )
void ForceCrashHandler( const char *reason ) void ForceCrashHandler( const char *reason )
{ {
CrashData crash; CrashData crash;
memset( &crash, 0, sizeof(crash) );
crash.type = CrashData::FORCE_CRASH_THIS_THREAD; crash.type = CrashData::FORCE_CRASH_THIS_THREAD;
strncpy( crash.reason, reason, sizeof(crash.reason) ); strncpy( crash.reason, reason, sizeof(crash.reason) );
crash.reason[ sizeof(crash.reason)-1 ] = 0; crash.reason[ sizeof(crash.reason)-1 ] = 0;
GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, NULL );
RunCrashHandler( &crash ); 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) #if !defined(DARWIN)
void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc ) void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc )
{ {
CrashData crash; CrashData crash;
memset( &crash, 0, sizeof(crash) );
crash.type = CrashData::SIGNAL; crash.type = CrashData::SIGNAL;
crash.signal = signal; crash.signal = signal;
crash.si = *si; crash.si = *si;
GetSignalBacktraceContext( &crash.ctx, uc ); BacktraceContext ctx;
GetSignalBacktraceContext( &ctx, uc );
GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, &ctx );
RunCrashHandler( &crash ); RunCrashHandler( &crash );
} }
#endif #endif
@@ -356,10 +372,15 @@ void CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc )
OSStatus CrashExceptionHandler( ExceptionInformation *e ) OSStatus CrashExceptionHandler( ExceptionInformation *e )
{ {
CrashData crash; CrashData crash;
memset( &crash, 0, sizeof(crash) );
crash.type = CrashData::OSX_EXCEPTION; crash.type = CrashData::OSX_EXCEPTION;
crash.kind = e->theKind; crash.kind = e->theKind;
GetExceptionBacktraceContext( &crash.ctx, e ); BacktraceContext ctx;
GetExceptionBacktraceContext( &ctx, e );
GetBacktrace( crash.BacktracePointers, BACKTRACE_MAX_SIZE, &ctx );
RunCrashHandler( &crash ); RunCrashHandler( &crash );
return -1; return -1;
} }
@@ -2,6 +2,8 @@
#define CRASH_HANDLER_H #define CRASH_HANDLER_H
void ForceCrashHandler( const char *reason ); void ForceCrashHandler( const char *reason );
struct BacktraceContext;
void ForceCrashHandlerDeadlock( const char *reason, const BacktraceContext *ctx );
void CrashHandlerHandleArgs( int argc, char* argv[] ); void CrashHandlerHandleArgs( int argc, char* argv[] );
void InitializeCrashHandler(); void InitializeCrashHandler();
@@ -27,7 +27,7 @@ extern const unsigned version_num;
const char *g_pCrashHandlerArgv0 = NULL; 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 ) if( BacktracePointers[0] == BACKTRACE_METHOD_NOT_AVAILABLE )
{ {
@@ -164,26 +164,22 @@ static void child_process()
{ {
int ret; int ret;
/* 1. Read the backtrace pointers. */ /* 1. Read the CrashData. */
void *BacktracePointers[BACKTRACE_MAX_SIZE];
ret = read(3, BacktracePointers, sizeof(void *)*BACKTRACE_MAX_SIZE);
/* 2. Read the CrashData. */
CrashData crash; CrashData crash;
ret = read(3, &crash, sizeof(CrashData)); ret = read(3, &crash, sizeof(CrashData));
/* 3. Read info. */ /* 2. Read info. */
int size; int size;
ret = read(3, &size, sizeof(size)); ret = read(3, &size, sizeof(size));
char *Info = new char [size]; char *Info = new char [size];
ret = read(3, Info, size); ret = read(3, Info, size);
/* 4. Read AdditionalLog. */ /* 3. Read AdditionalLog. */
ret = read(3, &size, sizeof(size)); ret = read(3, &size, sizeof(size));
char *AdditionalLog = new char [size]; char *AdditionalLog = new char [size];
ret = read(3, AdditionalLog, size); ret = read(3, AdditionalLog, size);
/* 5. Read RecentLogs. */ /* 4. Read RecentLogs. */
int cnt = 0; int cnt = 0;
ret = read(3, &cnt, sizeof(cnt)); ret = read(3, &cnt, sizeof(cnt));
char *Recent[1024]; char *Recent[1024];
@@ -194,7 +190,7 @@ static void child_process()
ret = read(3, Recent[i], size); ret = read(3, Recent[i], size);
} }
/* 6. Read CHECKPOINTs. */ /* 5. Read CHECKPOINTs. */
ret = read(3, &size, sizeof(size)); ret = read(3, &size, sizeof(size));
char *temp = new char [size]; char *temp = new char [size];
ret = read(3, temp, size); ret = read(3, temp, size);
@@ -202,7 +198,7 @@ static void child_process()
split(temp, "$$", Checkpoints); split(temp, "$$", Checkpoints);
delete [] temp; delete [] temp;
/* 7. Read the crashed thread's name. */ /* 6. Read the crashed thread's name. */
ret = read(3, &size, sizeof(size)); ret = read(3, &size, sizeof(size));
temp = new char [size]; temp = new char [size];
ret = read(3, temp, size); ret = read(3, temp, size);
@@ -270,6 +266,7 @@ static void child_process()
#endif #endif
case CrashData::FORCE_CRASH_THIS_THREAD: case CrashData::FORCE_CRASH_THIS_THREAD:
case CrashData::FORCE_CRASH_DEADLOCK:
crash.reason[ sizeof(crash.reason)-1] = 0; crash.reason[ sizeof(crash.reason)-1] = 0;
reason = crash.reason; reason = crash.reason;
break; break;
@@ -283,8 +280,14 @@ static void child_process()
fprintf(CrashDump, Checkpoints[i]); fprintf(CrashDump, Checkpoints[i]);
fprintf(CrashDump, "\n"); fprintf(CrashDump, "\n");
output_stack_trace( CrashDump, BacktracePointers ); output_stack_trace( CrashDump, crash.BacktracePointers );
fprintf(CrashDump, "\n"); 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, "Static log:\n");
fprintf(CrashDump, "%s", Info); fprintf(CrashDump, "%s", Info);
@@ -2,6 +2,7 @@
#define CRASH_HANDLER_INTERNAL_H #define CRASH_HANDLER_INTERNAL_H
#include "Backtrace.h" #include "Backtrace.h"
#define BACKTRACE_MAX_SIZE 1024
struct CrashData struct CrashData
{ {
@@ -19,14 +20,14 @@ struct CrashData
FORCE_CRASH_THIS_THREAD, FORCE_CRASH_THIS_THREAD,
/* Deadlock detected; give a stack trace for two threads. */ /* Deadlock detected; give a stack trace for two threads. */
// FORCE_CRASH_DEADLOCK FORCE_CRASH_DEADLOCK
} type; } type;
/* Everything except FORCE_CRASH_THIS_THREAD: */ /* Everything except FORCE_CRASH_THIS_THREAD: */
BacktraceContext ctx; const void *BacktracePointers[BACKTRACE_MAX_SIZE];
/* FORCE_CRASH_DEADLOCK only: */ /* FORCE_CRASH_DEADLOCK only: */
// BacktraceContext ctx2; const void *BacktracePointers2[BACKTRACE_MAX_SIZE];
/* SIGNAL only: */ /* SIGNAL only: */
int signal; int signal;
@@ -35,11 +36,10 @@ struct CrashData
/* OSX_EXCEPTION only: */ /* OSX_EXCEPTION only: */
int kind; int kind;
/* FORCE_CRASH_THIS_THREAD only: */ /* FORCE_CRASH_THIS_THREAD and FORCE_CRASH_DEADLOCK only: */
char reason[256]; char reason[256];
}; };
#define BACKTRACE_MAX_SIZE 1024
#define CHILD_MAGIC_PARAMETER "--private-do-crash-handler" #define CHILD_MAGIC_PARAMETER "--private-do-crash-handler"
const char *SignalName( int signo ); const char *SignalName( int signo );