|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <stdio.h>
|
|
Packit |
1fb8d4 |
#include <winpr/crt.h>
|
|
Packit |
1fb8d4 |
#include <winpr/windows.h>
|
|
Packit |
1fb8d4 |
#include <winpr/synch.h>
|
|
Packit |
1fb8d4 |
#include <winpr/sysinfo.h>
|
|
Packit |
1fb8d4 |
#include <winpr/thread.h>
|
|
Packit |
1fb8d4 |
#include <winpr/interlocked.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#define TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS 500
|
|
Packit |
1fb8d4 |
#define TEST_SYNC_CRITICAL_TEST1_RUNS 4
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static CRITICAL_SECTION critical;
|
|
Packit |
1fb8d4 |
static LONG gTestValueVulnerable = 0;
|
|
Packit |
1fb8d4 |
static LONG gTestValueSerialized = 0;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL TestSynchCritical_TriggerAndCheckRaceCondition(HANDLE OwningThread, LONG RecursionCount)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
/* if called unprotected this will hopefully trigger a race condition ... */
|
|
Packit |
1fb8d4 |
gTestValueVulnerable++;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (critical.OwningThread != OwningThread)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: OwningThread is invalid\n");
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
if (critical.RecursionCount != RecursionCount)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: RecursionCount is invalid\n");
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* ... which we try to detect using the serialized counter */
|
|
Packit |
1fb8d4 |
if (gTestValueVulnerable != InterlockedIncrement(&gTestValueSerialized))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Data corruption detected\n");
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
/* this thread function shall increment the global dwTestValue until the PBOOL passsed in arg is
|
|
Packit Service |
5a9772 |
* FALSE */
|
|
Packit |
1fb8d4 |
static DWORD WINAPI TestSynchCritical_Test1(LPVOID arg)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
int i, j, rc;
|
|
Packit Service |
5a9772 |
HANDLE hThread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
PBOOL pbContinueRunning = (PBOOL)arg;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
while (*pbContinueRunning)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
EnterCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
rc = 1;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc))
|
|
Packit |
1fb8d4 |
return 1;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* add some random recursion level */
|
|
Packit Service |
5a9772 |
j = rand() % 5;
|
|
Packit Service |
5a9772 |
for (i = 0; i < j; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc++))
|
|
Packit |
1fb8d4 |
return 2;
|
|
Packit |
1fb8d4 |
EnterCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
for (i = 0; i < j; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc--))
|
|
Packit |
1fb8d4 |
return 2;
|
|
Packit |
1fb8d4 |
LeaveCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!TestSynchCritical_TriggerAndCheckRaceCondition(hThread, rc))
|
|
Packit |
1fb8d4 |
return 3;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
LeaveCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
/* this thread function tries to call TryEnterCriticalSection while the main thread holds the lock
|
|
Packit Service |
5a9772 |
*/
|
|
Packit |
1fb8d4 |
static DWORD WINAPI TestSynchCritical_Test2(LPVOID arg)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
if (TryEnterCriticalSection(&critical) == TRUE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
LeaveCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
return 1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static DWORD WINAPI TestSynchCritical_Main(LPVOID arg)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
int i, j;
|
|
Packit |
1fb8d4 |
SYSTEM_INFO sysinfo;
|
|
Packit |
1fb8d4 |
DWORD dwPreviousSpinCount;
|
|
Packit |
1fb8d4 |
DWORD dwSpinCount;
|
|
Packit |
1fb8d4 |
DWORD dwSpinCountExpected;
|
|
Packit |
1fb8d4 |
HANDLE hMainThread;
|
|
Packit |
1fb8d4 |
HANDLE* hThreads;
|
|
Packit |
1fb8d4 |
HANDLE hThread;
|
|
Packit |
1fb8d4 |
DWORD dwThreadCount;
|
|
Packit |
1fb8d4 |
DWORD dwThreadExitCode;
|
|
Packit |
1fb8d4 |
BOOL bTest1Running;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
PBOOL pbThreadTerminated = (PBOOL)arg;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
GetNativeSystemInfo(&sysinfo);
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
hMainThread = (HANDLE)(ULONG_PTR)GetCurrentThreadId();
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit Service |
5a9772 |
* Test SpinCount in SetCriticalSectionSpinCount, InitializeCriticalSectionEx and
|
|
Packit Service |
5a9772 |
* InitializeCriticalSectionAndSpinCount SpinCount must be forced to be zero on on uniprocessor
|
|
Packit Service |
5a9772 |
* systems and on systems where WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT is defined
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
dwSpinCount = 100;
|
|
Packit |
1fb8d4 |
InitializeCriticalSectionEx(&critical, dwSpinCount, 0);
|
|
Packit Service |
5a9772 |
while (--dwSpinCount)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
dwPreviousSpinCount = SetCriticalSectionSpinCount(&critical, dwSpinCount);
|
|
Packit |
1fb8d4 |
dwSpinCountExpected = 0;
|
|
Packit |
1fb8d4 |
#if !defined(WINPR_CRITICAL_SECTION_DISABLE_SPINCOUNT)
|
|
Packit |
1fb8d4 |
if (sysinfo.dwNumberOfProcessors > 1)
|
|
Packit Service |
5a9772 |
dwSpinCountExpected = dwSpinCount + 1;
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
if (dwPreviousSpinCount != dwSpinCountExpected)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: SetCriticalSectionSpinCount returned %" PRIu32
|
|
Packit Service |
5a9772 |
" (expected: %" PRIu32 ")\n",
|
|
Packit Service |
5a9772 |
dwPreviousSpinCount, dwSpinCountExpected);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
DeleteCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if (dwSpinCount % 2 == 0)
|
|
Packit |
1fb8d4 |
InitializeCriticalSectionAndSpinCount(&critical, dwSpinCount);
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
InitializeCriticalSectionEx(&critical, dwSpinCount, 0);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
DeleteCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit Service |
5a9772 |
* Test single-threaded recursive
|
|
Packit Service |
5a9772 |
* TryEnterCriticalSection/EnterCriticalSection/LeaveCriticalSection
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
InitializeCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (i = 0; i < 1000; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (critical.RecursionCount != i)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: RecursionCount field is %" PRId32 " instead of %d.\n",
|
|
Packit Service |
5a9772 |
critical.RecursionCount, i);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit Service |
5a9772 |
if (i % 2 == 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
EnterCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
else
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (TryEnterCriticalSection(&critical) == FALSE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: TryEnterCriticalSection failed where it should "
|
|
Packit Service |
5a9772 |
"not.\n");
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
if (critical.OwningThread != hMainThread)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: Could not verify section ownership (loop index=%d).\n",
|
|
Packit Service |
5a9772 |
i);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
while (--i >= 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
LeaveCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
if (critical.RecursionCount != i)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: RecursionCount field is %" PRId32 " instead of %d.\n",
|
|
Packit Service |
5a9772 |
critical.RecursionCount, i);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
if (critical.OwningThread != (HANDLE)(i ? hMainThread : NULL))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: Could not verify section ownership (loop index=%d).\n",
|
|
Packit Service |
5a9772 |
i);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
DeleteCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* Test using multiple threads modifying the same value
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
dwThreadCount = sysinfo.dwNumberOfProcessors > 1 ? sysinfo.dwNumberOfProcessors : 2;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
hThreads = (HANDLE*)calloc(dwThreadCount, sizeof(HANDLE));
|
|
Packit |
1fb8d4 |
if (!hThreads)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("Problem allocating memory\n");
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (j = 0; j < TEST_SYNC_CRITICAL_TEST1_RUNS; j++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
dwSpinCount = j * 1000;
|
|
Packit |
1fb8d4 |
InitializeCriticalSectionAndSpinCount(&critical, dwSpinCount);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
gTestValueVulnerable = 0;
|
|
Packit |
1fb8d4 |
gTestValueSerialized = 0;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* the TestSynchCritical_Test1 threads shall run until bTest1Running is FALSE */
|
|
Packit |
1fb8d4 |
bTest1Running = TRUE;
|
|
Packit Service |
5a9772 |
for (i = 0; i < (int)dwThreadCount; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
if (!(hThreads[i] =
|
|
Packit Service |
5a9772 |
CreateThread(NULL, 0, TestSynchCritical_Test1, &bTest1Running, 0, NULL)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Failed to create test_1 thread #%d\n", i);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* let it run for TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS ... */
|
|
Packit |
1fb8d4 |
Sleep(TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS);
|
|
Packit |
1fb8d4 |
bTest1Running = FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
for (i = 0; i < (int)dwThreadCount; i++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (WaitForSingleObject(hThreads[i], INFINITE) != WAIT_OBJECT_0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Failed to wait for thread #%d\n", i);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
GetExitCodeThread(hThreads[i], &dwThreadExitCode);
|
|
Packit Service |
5a9772 |
if (dwThreadExitCode != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: Thread #%d returned error code %" PRIu32 "\n", i,
|
|
Packit Service |
5a9772 |
dwThreadExitCode);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
CloseHandle(hThreads[i]);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (gTestValueVulnerable != gTestValueSerialized)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: unexpected test value %" PRId32 " (expected %" PRId32
|
|
Packit Service |
5a9772 |
")\n",
|
|
Packit Service |
5a9772 |
gTestValueVulnerable, gTestValueSerialized);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
DeleteCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
free(hThreads);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* TryEnterCriticalSection in thread must fail if we hold the lock in the main thread
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
InitializeCriticalSection(&critical);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (TryEnterCriticalSection(&critical) == FALSE)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: TryEnterCriticalSection unexpectedly failed.\n");
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
/* This thread tries to call TryEnterCriticalSection which must fail */
|
|
Packit Service |
5a9772 |
if (!(hThread = CreateThread(NULL, 0, TestSynchCritical_Test2, NULL, 0, NULL)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Failed to create test_2 thread\n");
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
if (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Failed to wait for thread\n");
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
GetExitCodeThread(hThread, &dwThreadExitCode);
|
|
Packit Service |
5a9772 |
if (dwThreadExitCode != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
printf("CriticalSection failure: Thread returned error code %" PRIu32 "\n",
|
|
Packit Service |
5a9772 |
dwThreadExitCode);
|
|
Packit |
1fb8d4 |
goto fail;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
CloseHandle(hThread);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
*pbThreadTerminated = TRUE; /* requ. for winpr issue, see below */
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
fail:
|
|
Packit |
1fb8d4 |
*pbThreadTerminated = TRUE; /* requ. for winpr issue, see below */
|
|
Packit |
1fb8d4 |
return 1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
int TestSynchCritical(int argc, char* argv[])
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
BOOL bThreadTerminated = FALSE;
|
|
Packit |
1fb8d4 |
HANDLE hThread;
|
|
Packit |
1fb8d4 |
DWORD dwThreadExitCode;
|
|
Packit |
1fb8d4 |
DWORD dwDeadLockDetectionTimeMs;
|
|
Packit |
1fb8d4 |
DWORD i;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
dwDeadLockDetectionTimeMs =
|
|
Packit Service |
5a9772 |
2 * TEST_SYNC_CRITICAL_TEST1_RUNTIME_MS * TEST_SYNC_CRITICAL_TEST1_RUNS;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
printf("Deadlock will be assumed after %" PRIu32 " ms.\n", dwDeadLockDetectionTimeMs);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!(hThread = CreateThread(NULL, 0, TestSynchCritical_Main, &bThreadTerminated, 0, NULL)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Failed to create main thread\n");
|
|
Packit |
1fb8d4 |
return -1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* We have to be able to detect dead locks in this test.
|
|
Packit Service |
5a9772 |
* At the time of writing winpr's WaitForSingleObject has not implemented timeout for thread
|
|
Packit Service |
5a9772 |
* wait
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Workaround checking the value of bThreadTerminated which is passed in the thread arg
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (i = 0; i < dwDeadLockDetectionTimeMs; i += 100)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (bThreadTerminated)
|
|
Packit |
1fb8d4 |
break;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
Sleep(100);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!bThreadTerminated)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
printf("CriticalSection failure: Possible dead lock detected\n");
|
|
Packit |
1fb8d4 |
return -1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
GetExitCodeThread(hThread, &dwThreadExitCode);
|
|
Packit |
1fb8d4 |
CloseHandle(hThread);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (dwThreadExitCode != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
return -1;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|