void VMPI_ExceptionFilter( unsigned long uCode, void *pvExceptionInfo ) { // This is called if we crash inside our crash handler. It just terminates the process immediately. SetUnhandledExceptionFilter( VMPI_SecondExceptionFilter ); //DWORD code = ExceptionInfo->ExceptionRecord->ExceptionCode; #define ERR_RECORD( name ) { name, #name } struct { int code; char *pReason; } errors[] = { ERR_RECORD( EXCEPTION_ACCESS_VIOLATION ), ERR_RECORD( EXCEPTION_ARRAY_BOUNDS_EXCEEDED ), ERR_RECORD( EXCEPTION_BREAKPOINT ), ERR_RECORD( EXCEPTION_DATATYPE_MISALIGNMENT ), ERR_RECORD( EXCEPTION_FLT_DENORMAL_OPERAND ), ERR_RECORD( EXCEPTION_FLT_DIVIDE_BY_ZERO ), ERR_RECORD( EXCEPTION_FLT_INEXACT_RESULT ), ERR_RECORD( EXCEPTION_FLT_INVALID_OPERATION ), ERR_RECORD( EXCEPTION_FLT_OVERFLOW ), ERR_RECORD( EXCEPTION_FLT_STACK_CHECK ), ERR_RECORD( EXCEPTION_FLT_UNDERFLOW ), ERR_RECORD( EXCEPTION_ILLEGAL_INSTRUCTION ), ERR_RECORD( EXCEPTION_IN_PAGE_ERROR ), ERR_RECORD( EXCEPTION_INT_DIVIDE_BY_ZERO ), ERR_RECORD( EXCEPTION_INT_OVERFLOW ), ERR_RECORD( EXCEPTION_INVALID_DISPOSITION ), ERR_RECORD( EXCEPTION_NONCONTINUABLE_EXCEPTION ), ERR_RECORD( EXCEPTION_PRIV_INSTRUCTION ), ERR_RECORD( EXCEPTION_SINGLE_STEP ), ERR_RECORD( EXCEPTION_STACK_OVERFLOW ), ERR_RECORD( EXCEPTION_ACCESS_VIOLATION ), }; int nErrors = sizeof( errors ) / sizeof( errors[0] ); int i=0; char *pchReason = NULL; char chUnknownBuffer[32]; for ( i; ( i < nErrors ) && !pchReason; i++ ) { if ( errors[i].code == uCode ) pchReason = errors[i].pReason; } if ( i == nErrors ) { sprintf( chUnknownBuffer, "Error code 0x%08X", uCode ); pchReason = chUnknownBuffer; } VMPI_HandleCrash( pchReason, pvExceptionInfo, true ); TerminateProcess( GetCurrentProcess(), 1 ); }
SpewRetval_t CmdLib_SpewOutputFunc( SpewType_t type, char const *pMsg ) { // Hopefully two threads won't call this simultaneously right at the start! if ( !g_bSpewCSInitted ) { InitializeCriticalSection( &g_SpewCS ); g_bSpewCSInitted = true; } WORD old; SpewRetval_t retVal; EnterCriticalSection( &g_SpewCS ); { if (( type == SPEW_MESSAGE ) || (type == SPEW_LOG )) { old = SetConsoleTextColor( 1, 1, 1, 0 ); retVal = SPEW_CONTINUE; } else if( type == SPEW_WARNING ) { old = SetConsoleTextColor( 1, 1, 0, 1 ); retVal = SPEW_CONTINUE; } else if( type == SPEW_ASSERT ) { old = SetConsoleTextColor( 1, 0, 0, 1 ); retVal = SPEW_DEBUGGER; #ifdef MPI // VMPI workers don't want to bring up dialogs and suchlike. if ( g_bUseMPI && !g_bMPIMaster ) { VMPI_HandleCrash( pMsg, true ); exit( 0 ); } #endif } else if( type == SPEW_ERROR ) { old = SetConsoleTextColor( 1, 0, 0, 1 ); retVal = SPEW_ABORT; // doesn't matter.. we exit below so we can return an errorlevel (which dbg.dll doesn't do). } else { old = SetConsoleTextColor( 1, 1, 1, 1 ); retVal = SPEW_CONTINUE; } if ( !g_bSuppressPrintfOutput || type == SPEW_ERROR ) printf( "%s", pMsg ); OutputDebugString( pMsg ); if ( type == SPEW_ERROR ) { printf( "\n" ); OutputDebugString( "\n" ); } if( g_pLogFile ) { CmdLib_FPrintf( g_pLogFile, "%s", pMsg ); g_pFileSystem->Flush( g_pLogFile ); } // Dispatch to other spew hooks. FOR_EACH_LL( g_ExtraSpewHooks, i ) g_ExtraSpewHooks[i]( pMsg ); RestoreConsoleTextColor( old ); } LeaveCriticalSection( &g_SpewCS ); if ( type == SPEW_ERROR ) { CmdLib_Exit( 1 ); } return retVal; }
SpewRetval_t CmdLib_SpewOutputFunc( SpewType_t type, char const *pMsg ) { // Hopefully two threads won't call this simultaneously right at the start! if ( !g_bSpewCSInitted ) { InitializeCriticalSection( &g_SpewCS ); g_bSpewCSInitted = true; } WORD old; SpewRetval_t retVal; EnterCriticalSection( &g_SpewCS ); { if (( type == SPEW_MESSAGE ) || (type == SPEW_LOG )) { Color c = GetSpewOutputColor(); if ( c.r() != 255 || c.g() != 255 || c.b() != 255 ) { // custom color old = SetConsoleTextColor( c.r(), c.g(), c.b(), c.a() ); } else { old = SetConsoleTextColor( 1, 1, 1, 0 ); } retVal = SPEW_CONTINUE; } else if( type == SPEW_WARNING ) { old = SetConsoleTextColor( 1, 1, 0, 1 ); retVal = SPEW_CONTINUE; } else if( type == SPEW_ASSERT ) { old = SetConsoleTextColor( 1, 0, 0, 1 ); retVal = SPEW_DEBUGGER; #ifdef MPI // VMPI workers don't want to bring up dialogs and suchlike. // They need to have a special function installed to handle // the exceptions and write the minidumps. // Install the function after VMPI_Init with a call: // SetupToolsMinidumpHandler( VMPI_ExceptionFilter ); if ( g_bUseMPI && !g_bMPIMaster && !Plat_IsInDebugSession() ) { // Generating an exception and letting the // installed handler handle it ::RaiseException ( 0, // dwExceptionCode EXCEPTION_NONCONTINUABLE, // dwExceptionFlags 0, // nNumberOfArguments, NULL // const ULONG_PTR* lpArguments ); // Never get here (non-continuable exception) VMPI_HandleCrash( pMsg, NULL, true ); exit( 0 ); } #endif } else if( type == SPEW_ERROR ) { old = SetConsoleTextColor( 1, 0, 0, 1 ); retVal = SPEW_ABORT; // doesn't matter.. we exit below so we can return an errorlevel (which dbg.dll doesn't do). } else { old = SetConsoleTextColor( 1, 1, 1, 1 ); retVal = SPEW_CONTINUE; } if ( !g_bSuppressPrintfOutput || type == SPEW_ERROR ) printf( "%s", pMsg ); OutputDebugString( pMsg ); if ( type == SPEW_ERROR ) { printf( "\n" ); OutputDebugString( "\n" ); } if( g_pLogFile ) { CmdLib_FPrintf( g_pLogFile, "%s", pMsg ); g_pFileSystem->Flush( g_pLogFile ); } // Dispatch to other spew hooks. FOR_EACH_LL( g_ExtraSpewHooks, i ) g_ExtraSpewHooks[i]( pMsg ); RestoreConsoleTextColor( old ); } LeaveCriticalSection( &g_SpewCS ); if ( type == SPEW_ERROR ) { CmdLib_Exit( 1 ); } return retVal; }