void CmdLib_Cleanup() { CloseSpewFunctionLogFile(); CmdLib_TermFileSystem(); FOR_EACH_LL( g_CleanupFunctions, i ) g_CleanupFunctions[i](); #if defined( MPI ) // Unfortunately, when you call exit(), even if you have things registered with atexit(), // threads go into a seemingly undefined state where GetExitCodeThread gives STILL_ACTIVE // and WaitForSingleObject will stall forever on the thread. Because of this, we must cleanup // everything that uses threads before exiting. VMPI_Finalize(); #endif }
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; }