ForceCrashHandlerDeadlock
This commit is contained in:
@@ -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 );
|
||||||
|
|||||||
Reference in New Issue
Block a user