void CrashHandler::ForceDeadlock( RString reason, uint64_t iID ) { CrashData crash; memset( &crash, 0, sizeof(crash) ); crash.type = CrashData::FORCE_CRASH; GetBacktrace( crash.BacktracePointers[0], BACKTRACE_MAX_SIZE, NULL ); if( iID == GetInvalidThreadId() ) { /* Backtrace all threads. */ BacktraceAllThreads( crash ); } else { BacktraceContext ctx; if( !GetThreadBacktraceContext( iID, &ctx ) ) reason += "; GetThreadBacktraceContext failed"; else GetBacktrace( crash.BacktracePointers[1], BACKTRACE_MAX_SIZE, &ctx ); strncpy( crash.m_ThreadName[1], RageThread::GetThreadNameByID(iID), sizeof(crash.m_ThreadName[0])-1 ); } strncpy( crash.m_ThreadName[0], RageThread::GetCurrentThreadName(), sizeof(crash.m_ThreadName[0])-1 ); strncpy( crash.reason, reason, min(sizeof(crash.reason) - 1, reason.length()) ); crash.reason[ sizeof(crash.reason)-1 ] = 0; RunCrashHandler( &crash ); _exit( 1 ); }
void ReportBacktrace() { static const int framesToShow = 31; static const int framesToSkip = 2; void* samples[framesToShow + framesToSkip]; int frames = framesToShow + framesToSkip; GetBacktrace(samples, &frames); PrintBacktrace(samples + framesToSkip, frames - framesToSkip); }
void CrashHandler::ForceCrash( const char *reason ) { CrashData crash; memset( &crash, 0, sizeof(crash) ); crash.type = CrashData::FORCE_CRASH; strncpy( crash.reason, reason, sizeof(crash.reason) ); crash.reason[ sizeof(crash.reason)-1 ] = 0; GetBacktrace( crash.BacktracePointers[0], BACKTRACE_MAX_SIZE, NULL ); RunCrashHandler( &crash ); }
int TestGetBacktrace() { int size; int sizeMinus1; struct TBacktraceRecord* backtrace = GetBacktrace(&size, 0, 1); REQUIRE_NOT_EQUAL(backtrace, 0); REQUIRE_STRINGS_EQUAL(backtrace->Symbol_, "TestGetBacktrace"); REQUIRE_STRINGS_EQUAL(backtrace[1].Symbol_, "main"); free(backtrace); backtrace = GetBacktrace(&sizeMinus1, 1, 10); REQUIRE_NOT_EQUAL(backtrace, 0); REQUIRE_EQUAL(size - 1, sizeMinus1); REQUIRE_STRINGS_EQUAL(backtrace->Symbol_, "main"); free(backtrace); backtrace = GetBacktrace(&size, 100, 10); REQUIRE_EQUAL(backtrace, 0); REQUIRE_EQUAL(errno, ERANGE); backtrace = GetBacktrace(&size, 100, 0x7fffffff); REQUIRE_EQUAL(backtrace, 0); REQUIRE_EQUAL(errno, EDOM); return 0; }
void CrashHandler::ForceCrash( std::string const &reason ) { CrashData crash; std::memset( &crash, 0, sizeof(crash) ); crash.type = CrashData::FORCE_CRASH; std::strncpy( crash.reason, reason.c_str(), sizeof(crash.reason) ); crash.reason[ sizeof(crash.reason)-1 ] = 0; GetBacktrace( crash.BacktracePointers[0], BACKTRACE_MAX_SIZE, nullptr ); RunCrashHandler( &crash ); }
static void BacktraceAllThreads( CrashData& crash ) { int iCnt = 1; uint64_t iID; for( int i = 0; RageThread::EnumThreadIDs(i, iID); ++i ) { if( iID == GetInvalidThreadId() || iID == RageThread::GetCurrentThreadID() ) continue; BacktraceContext ctx; if( GetThreadBacktraceContext( iID, &ctx ) ) GetBacktrace( crash.BacktracePointers[iCnt], BACKTRACE_MAX_SIZE, &ctx ); strncpy( crash.m_ThreadName[iCnt], RageThread::GetThreadNameByID(iID), sizeof(crash.m_ThreadName[0])-1 ); ++iCnt; if( iCnt == CrashData::MAX_BACKTRACE_THREADS ) break; } }
void CrashHandler::CrashSignalHandler( int signal, siginfo_t *si, const ucontext_t *uc ) { static volatile bool bInCrashSignalHandler = false; if( bInCrashSignalHandler ) { safe_print( 2, "Fatal: crash from within the crash signal handler\n", NULL ); _exit(1); } bInCrashSignalHandler = true; /* Work around a gcc bug: it reorders the above assignment past other work down * here, even if we declare it volatile. This makes us not catch recursive * crashes. */ asm volatile("nop"); CrashData crash; memset( &crash, 0, sizeof(crash) ); crash.type = CrashData::SIGNAL; crash.signal = signal; crash.si = *si; BacktraceContext ctx; GetSignalBacktraceContext( &ctx, uc ); GetBacktrace( crash.BacktracePointers[0], BACKTRACE_MAX_SIZE, &ctx ); #if defined(HAVE_DECL_SIGUSR1) && HAVE_DECL_SIGUSR1 if( signal == SIGUSR1 ) BacktraceAllThreads( crash ); #endif strncpy( crash.m_ThreadName[0], RageThread::GetCurrentThreadName(), sizeof(crash.m_ThreadName[0])-1 ); bInCrashSignalHandler = false; /* RunCrashHandler handles any recursive crashes of its own by itself. */ RunCrashHandler( &crash ); }