1
0
Fork 0

Pump the event loop when waiting for a lock on the GUI thread

This solves a potential deadlock with DotX64dbg
This commit is contained in:
Duncan Ogilvie 2022-09-02 23:45:43 +02:00
parent d1f384e5bf
commit becfa86ac6
2 changed files with 50 additions and 6 deletions

View File

@ -57,9 +57,12 @@ SectionLockerGlobal::owner_info SectionLockerGlobal::m_owner[SectionLock::LockLa
CRITICAL_SECTION SectionLockerGlobal::m_crLocks[SectionLock::LockLast];
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_InitializeSRWLock;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockShared;
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockShared;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockExclusive;
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockExclusive;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockShared;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockExclusive;
DWORD SectionLockerGlobal::m_guiMainThreadId;
void SectionLockerGlobal::Initialize()
{
@ -68,17 +71,24 @@ void SectionLockerGlobal::Initialize()
if(m_Initialized)
return;
// This gets called on the same thread as the GUI
m_guiMainThreadId = GetCurrentThreadId();
// Attempt to read the SRWLock API
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
m_InitializeSRWLock = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "InitializeSRWLock");
m_AcquireSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockShared");
m_TryAcquireSRWLockShared = (TRYSRWLOCKFUNCTION)GetProcAddress(hKernel32, "TryAcquireSRWLockShared");
m_AcquireSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockExclusive");
m_TryAcquireSRWLockExclusive = (TRYSRWLOCKFUNCTION)GetProcAddress(hKernel32, "TryAcquireSRWLockExclusive");
m_ReleaseSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockShared");
m_ReleaseSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockExclusive");
m_SRWLocks = m_InitializeSRWLock &&
m_AcquireSRWLockShared &&
m_TryAcquireSRWLockShared &&
m_AcquireSRWLockExclusive &&
m_TryAcquireSRWLockExclusive &&
m_ReleaseSRWLockShared &&
m_ReleaseSRWLockExclusive;

View File

@ -90,33 +90,63 @@ public:
private:
static inline void AcquireLock(SectionLock LockIndex, bool Shared)
{
auto threadId = GetCurrentThreadId();
if(m_SRWLocks)
{
auto srwLock = &m_srwLocks[LockIndex];
if(Shared)
{
if(m_owner[LockIndex].thread == GetCurrentThreadId())
if(m_owner[LockIndex].thread == threadId)
return;
m_AcquireSRWLockShared(&m_srwLocks[LockIndex]);
if(threadId == m_guiMainThreadId)
{
while(!m_TryAcquireSRWLockShared(srwLock))
GuiProcessEvents();
}
else
{
m_AcquireSRWLockShared(srwLock);
}
return;
}
if(m_owner[LockIndex].thread == GetCurrentThreadId())
if(m_owner[LockIndex].thread == threadId)
{
assert(m_owner[LockIndex].count > 0);
m_owner[LockIndex].count++;
return;
}
m_AcquireSRWLockExclusive(&m_srwLocks[LockIndex]);
if(threadId == m_guiMainThreadId)
{
while(!m_TryAcquireSRWLockExclusive(srwLock))
GuiProcessEvents();
}
else
{
m_AcquireSRWLockExclusive(srwLock);
}
assert(m_owner[LockIndex].thread == 0);
assert(m_owner[LockIndex].count == 0);
m_owner[LockIndex].thread = GetCurrentThreadId();
m_owner[LockIndex].thread = threadId;
m_owner[LockIndex].count = 1;
}
else
EnterCriticalSection(&m_crLocks[LockIndex]);
{
auto cr = &m_crLocks[LockIndex];
if(threadId == m_guiMainThreadId)
{
while(!TryEnterCriticalSection(cr))
GuiProcessEvents();
}
else
{
EnterCriticalSection(cr);
}
}
}
static inline void ReleaseLock(SectionLock LockIndex, bool Shared)
@ -146,6 +176,7 @@ private:
}
typedef void (WINAPI* SRWLOCKFUNCTION)(PSRWLOCK SWRLock);
typedef BOOLEAN(WINAPI* TRYSRWLOCKFUNCTION)(PSRWLOCK SWRLock);
static bool m_Initialized;
static bool m_SRWLocks;
@ -155,9 +186,12 @@ private:
static CRITICAL_SECTION m_crLocks[SectionLock::LockLast];
static SRWLOCKFUNCTION m_InitializeSRWLock;
static SRWLOCKFUNCTION m_AcquireSRWLockShared;
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockShared;
static SRWLOCKFUNCTION m_AcquireSRWLockExclusive;
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockExclusive;
static SRWLOCKFUNCTION m_ReleaseSRWLockShared;
static SRWLOCKFUNCTION m_ReleaseSRWLockExclusive;
static DWORD m_guiMainThreadId;
};
template<SectionLock LockIndex, bool Shared>