//----------------------------------------------------------------------------- // XBX_InitConsoleMonitor // //----------------------------------------------------------------------------- void CXboxConsole::InitConsoleMonitor( bool bWaitForConnect ) { if ( XBX_NoXBDM() ) return; // create our events g_xbx_dbgValidEvent = CreateEvent( XBOX_DONTCARE, TRUE, FALSE, NULL ); g_xbx_dbgCmdCompleteEvent = CreateEvent( XBOX_DONTCARE, FALSE, FALSE, NULL ); // register our command handler with the debug monitor HRESULT hr = DmRegisterCommandProcessor( XBX_DBGCOMMANDPREFIX, _DebugCommandHandler ); if ( FAILED( hr ) ) { XBX_Error( "XBX_InitConsoleMonitor: failed to register command processor" ); } // user can have output bypass slave thread g_xbx_bDoSyncOutput = CommandLine()->FindParm( "-syncoutput" ) != 0; // create a slave thread to do delayed VXConsole transactions ThreadId_t threadID; g_xbx_hDebugThread = CreateSimpleThread( _DebugThreadFunc, NULL, &threadID, 16*1024 ); ThreadSetDebugName( threadID, "DebugThread" ); ThreadSetAffinity( g_xbx_hDebugThread, XBOX_PROCESSOR_5 ); if ( bWaitForConnect ) { XBX_DebugString( XBX_CLR_DEFAULT, "Waiting For VXConsole Connection...\n" ); WaitForSingleObject( g_xbx_dbgValidEvent, INFINITE ); } }
//----------------------------------------------------------------------------- // XBX_SendRemoteCommand // //----------------------------------------------------------------------------- void CXboxConsole::SendRemoteCommand( const char* dbgCommand, bool async ) { char cmdString[XBX_MAX_RCMDLENGTH]; if ( XBX_NoXBDM() || !IsConsoleConnected() ) return; AUTO_LOCK_FM( g_xbx_dbgChannelMutex ); _snprintf( cmdString, sizeof( cmdString ), "%s!%s", XBX_DBGCOMMANDPREFIX, dbgCommand ); HRESULT hr = DmSendNotificationString( cmdString ); if ( FAILED( hr ) ) { XBX_Error( "XBX_SendRemoteCommand: failed on %s", cmdString ); } // wait for command completion if ( !async ) { if (WaitForSingleObject( g_xbx_dbgCmdCompleteEvent, 5000 ) == WAIT_TIMEOUT) { // EGR Aug 22, 2007. debug failsafe added to prevent the console from mysteriously deadlocking during tests: // this will hang rather than halt: XBX_Error("XBX_SendRemoveCommant: timed out waiting for `%s` to complete", cmdString); // and these will also deadlock because the debug channel is inaccesssible: /* XBX_DebugString( XMAKECOLOR(255,0,0), "XBX_SendRemoveCommant: timed out waiting for `" ); XBX_DebugString( XMAKECOLOR(255,0,0), cmdString ); XBX_DebugString( XMAKECOLOR(255,0,0), "` to complete.\n" ); XBX_FlushDebugOutput(); DebuggerBreakIfDebugging(); */ // so we have no choice but to dump core: DmCrashDump(false); } } }
DBG_INTERFACE bool DoNewAssertDialog( const tchar *pFilename, int line, const tchar *pExpression ) { LOCAL_THREAD_LOCK(); if ( AreAssertsDisabled() ) return false; // If they have the old mode enabled (always break immediately), then just break right into // the debugger like we used to do. if ( IsDebugBreakEnabled() ) return true; // Have ALL Asserts been disabled? if ( !g_bAssertsEnabled ) return false; // Has this specific Assert been disabled? if ( !AreAssertsEnabledInFileLine( pFilename, line ) ) return false; // Now create the dialog. g_Info.m_pFilename = pFilename; g_Info.m_iLine = line; g_Info.m_pExpression = pExpression; g_bBreak = false; #if defined( _X360 ) char cmdString[XBX_MAX_RCMDLENGTH]; // Before calling VXConsole, init the global variable that receives the result g_VXConsoleAssertReturnValue = -1; // Message VXConsole to pop up a PC-side Assert dialog _snprintf( cmdString, sizeof(cmdString), "Assert() 0x%.8x File: %s\tLine: %d\t%s", &g_VXConsoleAssertReturnValue, pFilename, line, pExpression ); XBX_SendRemoteCommand( cmdString, false ); // We sent a synchronous message, so g_xbx_dbgVXConsoleAssertReturnValue should have been overwritten by now if ( g_VXConsoleAssertReturnValue == -1 ) { // VXConsole isn't connected/running - default to the old behaviour (break) g_bBreak = true; } else { // Respond to what the user selected switch( g_VXConsoleAssertReturnValue ) { case ASSERT_ACTION_IGNORE_FILE: IgnoreAssertsInCurrentFile(); break; case ASSERT_ACTION_IGNORE_THIS: // Ignore this Assert once break; case ASSERT_ACTION_BREAK: // Break on this Assert g_bBreak = true; break; case ASSERT_ACTION_IGNORE_ALL: // Ignore all Asserts from now on g_bAssertsEnabled = false; break; case ASSERT_ACTION_IGNORE_ALWAYS: // Ignore this Assert from now on IgnoreAssertsNearby( 0 ); break; case ASSERT_ACTION_OTHER: default: // Error... just break XBX_Error( "DoNewAssertDialog: invalid Assert response returned from VXConsole - breaking to debugger" ); g_bBreak = true; break; } } #elif defined( _WIN32 ) if ( !ThreadInMainThread() ) { int result = MessageBox( NULL, pExpression, "Assertion Failed", MB_SYSTEMMODAL | MB_CANCELTRYCONTINUE ); if ( result == IDCANCEL ) { IgnoreAssertsNearby( 0 ); } else if ( result == IDCONTINUE ) { g_bBreak = true; } } else { HWND hParentWindow = FindLikelyParentWindow(); DialogBox( g_hTier0Instance, MAKEINTRESOURCE( IDD_ASSERT_DIALOG ), hParentWindow, AssertDialogProc ); } #elif _LINUX fprintf(stderr, "%s %i %s", pFilename, line, pExpression); #endif return g_bBreak; }