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 );
}
Example #2
0
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;
}
Example #3
0
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;
}