mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-03-13 22:32:32 +00:00
Make DebuggerServer portable (use SDL instead of WinAPI)
This commit is contained in:
parent
85167fa180
commit
6b6b28a401
5 changed files with 65 additions and 43 deletions
|
@ -34,7 +34,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "idlib/containers/HashIndex.h"
|
||||
#include "idlib/math/Vector.h"
|
||||
|
||||
//#include "GameBase.h"
|
||||
#include "GameBase.h"
|
||||
|
||||
class idEventDef;
|
||||
class idVarDef;
|
||||
|
|
|
@ -594,7 +594,7 @@ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOn
|
|||
msg.WriteBits ( onceOnly?1:0, 1 );
|
||||
msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) );
|
||||
msg.WriteInt ( bp.GetID ( ) );
|
||||
msg.WriteString ( bp.GetFilename() );
|
||||
msg.WriteString ( bp.GetFilename() ); // FIXME: this implies make7bit ?!
|
||||
|
||||
SendPacket ( msg.GetData(), msg.GetSize() );
|
||||
}
|
||||
|
|
|
@ -50,10 +50,17 @@ rvDebuggerServer::rvDebuggerServer ( )
|
|||
mBreak = false;
|
||||
mBreakStepOver = false;
|
||||
mBreakStepInto = false;
|
||||
mGameThread = NULL;
|
||||
mGameThreadBreakCond = NULL;
|
||||
mGameThreadBreakLock = NULL;
|
||||
mLastStatementLine = -1;
|
||||
mBreakStepOverFunc1 = NULL;
|
||||
mBreakStepOverFunc2 = NULL;
|
||||
mBreakInstructionPointer = 0;
|
||||
mBreakInterpreter = NULL;
|
||||
mBreakProgram = NULL;
|
||||
mGameDLLHandle = 0;
|
||||
mBreakStepOverDepth = 0;
|
||||
mCriticalSection = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -81,12 +88,14 @@ bool rvDebuggerServer::Initialize ( void )
|
|||
return false;
|
||||
}
|
||||
|
||||
// Get a copy of the game thread handle so we can suspend the thread on a break
|
||||
DuplicateHandle ( GetCurrentProcess(), GetCurrentThread ( ), GetCurrentProcess(), &mGameThread, 0, FALSE, DUPLICATE_SAME_ACCESS );
|
||||
// we're using a condition variable to pause the game thread in rbDebuggerServer::Break()
|
||||
// until rvDebuggerServer::Resume() is called (from another thread)
|
||||
mGameThreadBreakCond = SDL_CreateCond();
|
||||
mGameThreadBreakLock = SDL_CreateMutex();
|
||||
|
||||
// Create a critical section to ensure that the shared thread
|
||||
// variables are protected
|
||||
InitializeCriticalSection ( &mCriticalSection );
|
||||
mCriticalSection = SDL_CreateMutex();
|
||||
|
||||
// Server must be running on the local host on port 28980
|
||||
Sys_StringToNetAdr ( "localhost", &mClientAdr, true );
|
||||
|
@ -129,8 +138,16 @@ void rvDebuggerServer::Shutdown ( void )
|
|||
|
||||
mPort.Close();
|
||||
|
||||
Resume(); // just in case we're still paused
|
||||
|
||||
// dont need the crit section anymore
|
||||
DeleteCriticalSection ( &mCriticalSection );
|
||||
SDL_DestroyMutex( mCriticalSection );
|
||||
mCriticalSection = NULL;
|
||||
|
||||
SDL_DestroyCond( mGameThreadBreakCond );
|
||||
mGameThreadBreakCond = NULL;
|
||||
SDL_DestroyMutex( mGameThreadBreakLock );
|
||||
mGameThreadBreakLock = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -274,14 +291,14 @@ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg )
|
|||
bool onceOnly = false;
|
||||
long lineNumber;
|
||||
long id;
|
||||
char filename[MAX_PATH];
|
||||
char filename[2048]; // DG: randomly chose this size
|
||||
|
||||
// Read the breakpoint info
|
||||
onceOnly = msg->ReadBits ( 1 ) ? true : false;
|
||||
lineNumber = msg->ReadInt ( );
|
||||
id = msg->ReadInt ( );
|
||||
|
||||
msg->ReadString ( filename, MAX_PATH );
|
||||
msg->ReadString ( filename, sizeof(filename) );
|
||||
|
||||
//check for statement on requested breakpoint location
|
||||
if (!gameEdit->IsLineCode(filename, lineNumber))
|
||||
|
@ -299,9 +316,9 @@ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg )
|
|||
}
|
||||
|
||||
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
SDL_LockMutex( mCriticalSection );
|
||||
mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) );
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
SDL_UnlockMutex( mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -323,7 +340,7 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( idBitMsg* msg )
|
|||
|
||||
// Since breakpoints are used by both threads we need to
|
||||
// protect them with a crit section
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
SDL_LockMutex( mCriticalSection );
|
||||
|
||||
// Find the breakpoint that matches the given id and remove it from the list
|
||||
for ( i = 0; i < mBreakpoints.Num(); i ++ )
|
||||
|
@ -336,7 +353,7 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( idBitMsg* msg )
|
|||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
SDL_UnlockMutex( mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -543,7 +560,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
OSPathToRelativePath(filename,qpath);
|
||||
qpath.BackSlashesToSlashes ( );
|
||||
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
SDL_LockMutex( mCriticalSection );
|
||||
|
||||
// Check all the breakpoints
|
||||
for ( i = 0; i < mBreakpoints.Num ( ); i ++ )
|
||||
|
@ -563,19 +580,19 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram*
|
|||
}
|
||||
|
||||
// Pop out of the critical section so we dont get stuck
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
SDL_UnlockMutex( mCriticalSection );
|
||||
|
||||
HandleInspectScripts(nullptr);
|
||||
// We hit a breakpoint, so break
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
|
||||
// Back into the critical section since we are going to have to leave it
|
||||
EnterCriticalSection ( &mCriticalSection );
|
||||
SDL_LockMutex( mCriticalSection );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
SDL_UnlockMutex( mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -625,18 +642,26 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i
|
|||
|
||||
// Suspend the game thread. Since this will be called from within the main game thread
|
||||
// execution wont return until after the thread is resumed
|
||||
SuspendThread ( mGameThread );
|
||||
// DG: the original code used Win32 SuspendThread() here, but as there is no equivalent
|
||||
// function in SDL and as this is only called within the main game thread anyway,
|
||||
// just use a condition variable to put this thread to sleep until Resume() has set mBreak
|
||||
SDL_LockMutex( mGameThreadBreakLock );
|
||||
while ( mBreak ) {
|
||||
SDL_CondWait( mGameThreadBreakCond, mGameThreadBreakLock );
|
||||
}
|
||||
SDL_UnlockMutex( mGameThreadBreakLock );
|
||||
|
||||
// Let the debugger client know that we have started back up again
|
||||
SendMessage ( DBMSG_RESUMED );
|
||||
|
||||
// this should be platform specific
|
||||
// TODO: maybe replace with SDL code? or does it not matter if debugger client runs on another machine?
|
||||
#if defined( ID_ALLOW_TOOLS )
|
||||
// This is to give some time between the keypress that
|
||||
// told us to resume and the setforeground window. Otherwise the quake window
|
||||
// would just flash
|
||||
Sleep ( 150 );
|
||||
|
||||
//this should be platform specific
|
||||
#if defined( ID_ALLOW_TOOLS )
|
||||
// Bring the window back to the foreground
|
||||
SetForegroundWindow ( win32.hWnd );
|
||||
SetActiveWindow ( win32.hWnd );
|
||||
|
@ -671,7 +696,10 @@ void rvDebuggerServer::Resume ( void )
|
|||
mBreak = false;
|
||||
|
||||
// Start the game thread back up
|
||||
ResumeThread ( mGameThread );
|
||||
SDL_LockMutex( mGameThreadBreakLock );
|
||||
mBreak = true;
|
||||
SDL_CondSignal( mGameThreadBreakCond);
|
||||
SDL_UnlockMutex( mGameThreadBreakLock );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -32,6 +32,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "DebuggerMessages.h"
|
||||
#include "DebuggerBreakpoint.h"
|
||||
#include "framework/Game.h"
|
||||
#include <SDL.h>
|
||||
|
||||
|
||||
|
||||
|
@ -83,11 +84,13 @@ private:
|
|||
netadr_t mClientAdr;
|
||||
idPort mPort;
|
||||
idList<rvDebuggerBreakpoint*> mBreakpoints;
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
SDL_mutex* mCriticalSection;
|
||||
|
||||
HANDLE mGameThread;
|
||||
|
||||
SDL_cond* mGameThreadBreakCond;
|
||||
SDL_mutex* mGameThreadBreakLock;
|
||||
bool mBreak;
|
||||
|
||||
bool mBreakNext;
|
||||
bool mBreakStepOver;
|
||||
bool mBreakStepInto;
|
||||
|
|
|
@ -36,20 +36,14 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "DebuggerServer.h"
|
||||
|
||||
DWORD CALLBACK DebuggerThread ( LPVOID param );
|
||||
|
||||
#if defined( ID_ALLOW_TOOLS )
|
||||
rvDebuggerApp gDebuggerApp;
|
||||
HWND gDebuggerWindow = NULL;
|
||||
rvDebuggerApp gDebuggerApp; // this is also used in other source files
|
||||
static HWND gDebuggerWindow = NULL;
|
||||
#endif
|
||||
bool gDebuggerSuspend = false;
|
||||
bool gDebuggerConnnected = false;
|
||||
HANDLE gDebuggerGameThread = NULL;
|
||||
|
||||
rvDebuggerServer* gDebuggerServer = NULL;
|
||||
HANDLE gDebuggerServerThread = NULL;
|
||||
DWORD gDebuggerServerThreadID = 0;
|
||||
bool gDebuggerServerQuit = false;
|
||||
static rvDebuggerServer* gDebuggerServer = NULL;
|
||||
static SDL_Thread* gDebuggerServerThread = NULL;
|
||||
static bool gDebuggerServerQuit = false;
|
||||
|
||||
#if defined( ID_ALLOW_TOOLS )
|
||||
/*
|
||||
|
@ -128,14 +122,14 @@ DebuggerServerThread
|
|||
Thread proc for the debugger server
|
||||
================
|
||||
*/
|
||||
DWORD CALLBACK DebuggerServerThread ( LPVOID param )
|
||||
static int SDLCALL DebuggerServerThread ( void *param )
|
||||
{
|
||||
assert ( gDebuggerServer );
|
||||
|
||||
while ( !gDebuggerServerQuit )
|
||||
{
|
||||
gDebuggerServer->ProcessMessages ( );
|
||||
Sleep ( 1 );
|
||||
SDL_Delay( 1 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -172,7 +166,7 @@ bool DebuggerServerInit ( void )
|
|||
}
|
||||
|
||||
// Start the debugger server thread
|
||||
gDebuggerServerThread = CreateThread ( NULL, 0, DebuggerServerThread, 0, 0, &gDebuggerServerThreadID );
|
||||
gDebuggerServerThread = SDL_CreateThread( DebuggerServerThread, "DebuggerServer", NULL );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -186,23 +180,20 @@ Shuts down the debugger server
|
|||
*/
|
||||
void DebuggerServerShutdown ( void )
|
||||
{
|
||||
if ( gDebuggerServerThread )
|
||||
if ( gDebuggerServerThread != NULL )
|
||||
{
|
||||
// Signal the debugger server to quit
|
||||
gDebuggerServerQuit = true;
|
||||
|
||||
// Wait for the thread to finish
|
||||
WaitForSingleObject ( gDebuggerServerThread, INFINITE );
|
||||
SDL_WaitThread( gDebuggerServerThread, NULL );
|
||||
gDebuggerServerThread = NULL;
|
||||
|
||||
// Shutdown the server now
|
||||
gDebuggerServer->Shutdown();
|
||||
|
||||
delete gDebuggerServer;
|
||||
gDebuggerServer = NULL;
|
||||
|
||||
// Cleanup the thread handle
|
||||
CloseHandle ( gDebuggerServerThread );
|
||||
gDebuggerServerThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue