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