ForceCrashHandlerDeadlock takes an ID
handle iID == GetInvalidThreadId() for "all"
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
|
|
||||||
|
#include "arch/Threads/Threads_Win32.h"
|
||||||
#include "archutils/win32/WindowsResources.h"
|
#include "archutils/win32/WindowsResources.h"
|
||||||
#include "crash.h"
|
#include "crash.h"
|
||||||
#include "ProductInfo.h"
|
#include "ProductInfo.h"
|
||||||
@@ -123,14 +124,19 @@ static const char *LookupException( DWORD code )
|
|||||||
struct CrashInfo
|
struct CrashInfo
|
||||||
{
|
{
|
||||||
char m_CrashReason[256];
|
char m_CrashReason[256];
|
||||||
|
|
||||||
const void *m_BacktracePointers[BACKTRACE_MAX_SIZE];
|
const void *m_BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||||
|
|
||||||
const void *m_AlternateThreadBacktrace[BACKTRACE_MAX_SIZE];
|
enum { MAX_BACKTRACE_THREADS = 32 };
|
||||||
|
const void *m_AlternateThreadBacktrace[MAX_BACKTRACE_THREADS][BACKTRACE_MAX_SIZE];
|
||||||
|
char m_AlternateThreadName[MAX_BACKTRACE_THREADS][128];
|
||||||
|
|
||||||
CrashInfo()
|
CrashInfo()
|
||||||
{
|
{
|
||||||
m_CrashReason[0] = 0;
|
m_CrashReason[0] = 0;
|
||||||
m_BacktracePointers[0] = m_AlternateThreadBacktrace[0] = NULL;
|
memset( m_AlternateThreadBacktrace, 0, sizeof(m_AlternateThreadBacktrace) );
|
||||||
|
memset( m_AlternateThreadName, 0, sizeof(m_AlternateThreadName) );
|
||||||
|
m_BacktracePointers[0] = NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -797,12 +803,17 @@ static void DoSave()
|
|||||||
|
|
||||||
if( g_CrashInfo.m_AlternateThreadBacktrace[0] )
|
if( g_CrashInfo.m_AlternateThreadBacktrace[0] )
|
||||||
{
|
{
|
||||||
Report( NULL, hFile, "Deadlocked with:" );
|
for( int i = 0; i < CrashInfo::MAX_BACKTRACE_THREADS; ++i )
|
||||||
Report( NULL, hFile, "" );
|
{
|
||||||
|
if( !g_CrashInfo.m_AlternateThreadBacktrace[i][0] )
|
||||||
|
continue;
|
||||||
|
|
||||||
ReportCallStack( NULL, hFile, g_CrashInfo.m_AlternateThreadBacktrace );
|
Report( NULL, hFile, "Thread %s:", g_CrashInfo.m_AlternateThreadName[i] );
|
||||||
|
Report( NULL, hFile, "" );
|
||||||
|
ReportCallStack( NULL, hFile, g_CrashInfo.m_AlternateThreadBacktrace[i] );
|
||||||
Report(NULL, hFile, "");
|
Report(NULL, hFile, "");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Report(NULL, hFile, "Static log:");
|
Report(NULL, hFile, "Static log:");
|
||||||
WriteBuf( hFile, RageLog::GetInfo() );
|
WriteBuf( hFile, RageLog::GetInfo() );
|
||||||
@@ -936,22 +947,31 @@ void NORETURN debug_crash()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a stack trace of the current thread and the specified thread. */
|
/* Get a stack trace of the current thread and the specified thread. If
|
||||||
void ForceCrashHandlerDeadlock( CString reason, uint64_t iThreadHandle )
|
* iID == GetInvalidThreadId(), then output a stack trace for every thread. */
|
||||||
|
void ForceCrashHandlerDeadlock( CString reason, uint64_t iID )
|
||||||
{
|
{
|
||||||
HANDLE hThread = (HANDLE) iThreadHandle;
|
|
||||||
|
|
||||||
strncpy( g_CrashInfo.m_CrashReason, reason, sizeof(g_CrashInfo.m_CrashReason) );
|
strncpy( g_CrashInfo.m_CrashReason, reason, sizeof(g_CrashInfo.m_CrashReason) );
|
||||||
g_CrashInfo.m_CrashReason[ sizeof(g_CrashInfo.m_CrashReason)-1 ] = 0;
|
g_CrashInfo.m_CrashReason[ sizeof(g_CrashInfo.m_CrashReason)-1 ] = 0;
|
||||||
|
|
||||||
if( hThread == NULL )
|
|
||||||
{
|
|
||||||
strcat( g_CrashInfo.m_CrashReason, "(hThread == NULL)" );
|
|
||||||
} else {
|
|
||||||
/* Suspend the other thread we're going to backtrace. (We need to at least suspend
|
/* Suspend the other thread we're going to backtrace. (We need to at least suspend
|
||||||
* hThread, for GetThreadContext to work.) */
|
* hThread, for GetThreadContext to work.) */
|
||||||
RageThread::HaltAllThreads( false );
|
RageThread::HaltAllThreads( false );
|
||||||
|
|
||||||
|
if( iID == GetInvalidThreadId() )
|
||||||
|
{
|
||||||
|
/* Backtrace all threads. */
|
||||||
|
int iCnt = 0;
|
||||||
|
for( int i = 0; RageThread::EnumThreadIDs(i, iID); ++i )
|
||||||
|
{
|
||||||
|
if( iID == GetInvalidThreadId() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( iID == GetCurrentThreadId() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const HANDLE hThread = Win32ThreadIdToHandle( iID );
|
||||||
|
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
context.ContextFlags = CONTEXT_FULL;
|
context.ContextFlags = CONTEXT_FULL;
|
||||||
if( !GetThreadContext( hThread, &context ) )
|
if( !GetThreadContext( hThread, &context ) )
|
||||||
@@ -959,7 +979,31 @@ void ForceCrashHandlerDeadlock( CString reason, uint64_t iThreadHandle )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
static const void *BacktracePointers[BACKTRACE_MAX_SIZE];
|
static const void *BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||||
do_backtrace( g_CrashInfo.m_AlternateThreadBacktrace, BACKTRACE_MAX_SIZE, GetCurrentProcess(), hThread, &context );
|
do_backtrace( g_CrashInfo.m_AlternateThreadBacktrace[iCnt], BACKTRACE_MAX_SIZE, GetCurrentProcess(), hThread, &context );
|
||||||
|
|
||||||
|
const char *pName = RageThread::GetThreadNameByID( iID );
|
||||||
|
strncpy( g_CrashInfo.m_AlternateThreadName[iCnt], pName? pName:"???", sizeof(g_CrashInfo.m_AlternateThreadName[iCnt])-1 );
|
||||||
|
|
||||||
|
++iCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iCnt == CrashInfo::MAX_BACKTRACE_THREADS )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const HANDLE hThread = Win32ThreadIdToHandle( iID );
|
||||||
|
|
||||||
|
CONTEXT context;
|
||||||
|
context.ContextFlags = CONTEXT_FULL;
|
||||||
|
if( !GetThreadContext( hThread, &context ) )
|
||||||
|
strcat( g_CrashInfo.m_CrashReason, "(GetThreadContext failed)" );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const void *BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||||
|
do_backtrace( g_CrashInfo.m_AlternateThreadBacktrace[0], BACKTRACE_MAX_SIZE, GetCurrentProcess(), hThread, &context );
|
||||||
|
|
||||||
|
const char *pName = RageThread::GetThreadNameByID( iID );
|
||||||
|
strncpy( g_CrashInfo.m_AlternateThreadName[0], pName? pName:"???", sizeof(g_CrashInfo.m_AlternateThreadName[0])-1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user