1
0
Fork 0

Fix a race condition when spamming restarts

This commit is contained in:
Duncan Ogilvie 2021-03-16 01:09:45 +01:00
parent 64d808e07c
commit d5e265a501
3 changed files with 40 additions and 31 deletions

View File

@ -133,14 +133,11 @@ bool cbDebugInit(int argc, char* argv[])
strcpy_s(currentfolder, arg3);
static INIT_STRUCT init;
memset(&init, 0, sizeof(INIT_STRUCT));
init.exe = arg1;
init.commandline = commandline;
if(*currentfolder)
init.currentfolder = currentfolder;
hDebugLoopThread = CreateThread(nullptr, 0, threadDebugLoop, &init, CREATE_SUSPENDED, nullptr);
ResumeThread(hDebugLoopThread);
dbgcreatedebugthread(&init);
return true;
}
@ -258,8 +255,10 @@ bool cbDebugAttach(int argc, char* argv[])
if(tid)
dbgsetresumetid(tid);
}
hDebugLoopThread = CreateThread(nullptr, 0, threadAttachLoop, (void*)pid, CREATE_SUSPENDED, nullptr);
ResumeThread(hDebugLoopThread);
static INIT_STRUCT init;
init.attach = true;
init.pid = (DWORD)pid;
dbgcreatedebugthread(&init);
return true;
}

View File

@ -2654,27 +2654,23 @@ static void* InitDLLDebugW(const wchar_t* szFileName, const wchar_t* szCommandLi
return ReturnValue;
}
static void debugLoopFunction(void* lpParameter, bool attach)
static void debugLoopFunction(INIT_STRUCT* init)
{
//initialize variables
bIsAttached = attach;
bIsAttached = init->attach;
dbgsetskipexceptions(false);
bFreezeStack = false;
//prepare attach/createprocess
DWORD pid;
INIT_STRUCT* init;
if(attach)
if(init->attach)
{
gInitExe = StringUtils::Utf8ToUtf16(szDebuggeePath);
pid = DWORD(lpParameter);
static PROCESS_INFORMATION pi_attached;
memset(&pi_attached, 0, sizeof(pi_attached));
fdProcessInfo = &pi_attached;
}
else
{
init = (INIT_STRUCT*)lpParameter;
gInitExe = StringUtils::Utf8ToUtf16(init->exe);
strcpy_s(szDebuggeePath, init->exe);
}
@ -2690,7 +2686,7 @@ static void debugLoopFunction(void* lpParameter, bool attach)
}
DbSetPath(nullptr, szDebuggeePath);
if(!attach)
if(!init->attach)
{
// Load command line if it exists in DB
DbLoad(DbLoadSaveType::CommandLine);
@ -2771,6 +2767,10 @@ static void debugLoopFunction(void* lpParameter, bool attach)
gInitDir.clear();
}
// signal that fdProcessInfo has been set
SetEvent(init->event);
init->event = nullptr;
//set custom handlers
SetCustomHandler(UE_CH_CREATEPROCESS, (void*)cbCreateProcess);
SetCustomHandler(UE_CH_EXITPROCESS, (void*)cbExitProcess);
@ -2803,10 +2803,10 @@ static void debugLoopFunction(void* lpParameter, bool attach)
plugincbcall(CB_INITDEBUG, &initInfo);
//call plugin callback (attach)
if(attach)
if(init->attach)
{
PLUG_CB_ATTACH attachInfo;
attachInfo.dwProcessId = (DWORD)pid;
attachInfo.dwProcessId = init->pid;
plugincbcall(CB_ATTACH, &attachInfo);
}
@ -2814,9 +2814,9 @@ static void debugLoopFunction(void* lpParameter, bool attach)
DbLoad(DbLoadSaveType::DebugData);
//run debug loop (returns when process debugging is stopped)
if(attach)
if(init->attach)
{
if(AttachDebugger(pid, true, fdProcessInfo, (void*)cbAttachDebugger) == false)
if(AttachDebugger(init->pid, true, fdProcessInfo, (void*)cbAttachDebugger) == false)
{
String error = stringformatinline(StringUtils::sprintf("{winerror@%d}", GetLastError()));
dprintf(QT_TRANSLATE_NOOP("DBG", "Attach to process failed! GetLastError() = %s\n"), error.c_str());
@ -2902,16 +2902,24 @@ void dbgsetforeground()
SetForegroundWindow(GuiGetWindowHandle());
}
DWORD WINAPI threadDebugLoop(void* lpParameter)
void dbgcreatedebugthread(INIT_STRUCT* init)
{
debugLoopFunction(lpParameter, false);
return 0;
}
auto event = init->event = CreateEventW(nullptr, false, false, nullptr);
hDebugLoopThread = CreateThread(nullptr, 0, [](LPVOID lpParameter) -> DWORD
{
auto init = (INIT_STRUCT*)lpParameter;
debugLoopFunction(init);
DWORD WINAPI threadAttachLoop(void* lpParameter)
{
debugLoopFunction(lpParameter, true);
return 0;
// Set the event in case debugLoopFunction returned early to prevent a deadlock
if(init->event)
{
SetEvent(init->event);
init->event = nullptr;
}
return 0;
}, init, 0, nullptr);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
bool dbgrestartadmin()

View File

@ -27,9 +27,12 @@ enum class ExceptionHandledBy
//structures
struct INIT_STRUCT
{
char* exe;
char* commandline;
char* currentfolder;
HANDLE event = nullptr;
char* exe = nullptr;
char* commandline = nullptr;
char* currentfolder = nullptr;
DWORD pid = 0;
bool attach = false;
};
struct ExceptionRange
@ -103,6 +106,7 @@ void dbgtracebrowserneedsupdate();
bool dbgsetdllbreakpoint(const char* mod, DWORD type, bool singleshoot);
bool dbgdeletedllbreakpoint(const char* mod, DWORD type);
void dbgsetdebugflags(DWORD flags);
void dbgcreatedebugthread(INIT_STRUCT* init);
void cbStep();
void cbRtrStep();
@ -112,7 +116,6 @@ void cbMemoryBreakpoint(void* ExceptionAddress);
void cbHardwareBreakpoint(void* ExceptionAddress);
void cbUserBreakpoint();
void cbDebugLoadLibBPX();
DWORD WINAPI threadDebugLoop(void* lpParameter);
void cbTraceOverConditionalStep();
void cbTraceIntoConditionalStep();
void cbTraceIntoBeyondTraceRecordStep();
@ -120,7 +123,6 @@ void cbTraceOverBeyondTraceRecordStep();
void cbTraceIntoIntoTraceRecordStep();
void cbTraceOverIntoTraceRecordStep();
void cbRunToUserCodeBreakpoint(void* ExceptionAddress);
DWORD WINAPI threadAttachLoop(void* lpParameter);
bool cbSetModuleBreakpoints(const BREAKPOINT* bp);
EXCEPTION_DEBUG_INFO & getLastExceptionInfo();
bool dbgrestartadmin();