libwinpr-synch: fix race condition in event handling

This commit is contained in:
Marc-André Moreau 2012-12-03 14:57:15 -05:00
parent 7140acd506
commit d8fa43c526
5 changed files with 82 additions and 38 deletions

View File

@ -25,7 +25,7 @@
#include <unistd.h>
#include <winpr/crt.h>
#include <winpr/synch.>
#include <winpr/synch.h>
#include "searchman.h"

View File

@ -145,6 +145,7 @@ typedef struct _RTL_CRITICAL_SECTION
ULONG SpinCount;
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
typedef PRTL_CRITICAL_SECTION PCRITICAL_SECTION;
typedef PRTL_CRITICAL_SECTION LPCRITICAL_SECTION;

View File

@ -23,22 +23,34 @@
#include <winpr/synch.h>
/**
* InitializeCriticalSection
* InitializeCriticalSectionAndSpinCount
* InitializeCriticalSectionEx
* SetCriticalSectionSpinCount
* EnterCriticalSection
* TryEnterCriticalSection
* LeaveCriticalSection
* DeleteCriticalSection
*/
#include "synch.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef _WIN32
VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
if (lpCriticalSection)
{
lpCriticalSection->DebugInfo = NULL;
lpCriticalSection->LockCount = 0;
lpCriticalSection->RecursionCount = 0;
lpCriticalSection->SpinCount = 0;
lpCriticalSection->OwningThread = NULL;
lpCriticalSection->LockSemaphore = NULL;
lpCriticalSection->LockSemaphore = (winpr_sem_t*) malloc(sizeof(winpr_sem_t));
#if defined __APPLE__
semaphore_create(mach_task_self(), lpCriticalSection->LockSemaphore, SYNC_POLICY_FIFO, 1);
#else
sem_init(lpCriticalSection->LockSemaphore, 0, 1);
#endif
}
}
BOOL InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags)
@ -58,7 +70,11 @@ DWORD SetCriticalSectionSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dw
VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
#if defined __APPLE__
semaphore_wait(*((winpr_sem_t*) lpCriticalSection->LockSemaphore));
#else
sem_wait((winpr_sem_t*) lpCriticalSection->LockSemaphore);
#endif
}
BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
@ -68,12 +84,20 @@ BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
#if defined __APPLE__
semaphore_signal(*((winpr_sem_t*) lpCriticalSection->LockSemaphore));
#else
sem_post((winpr_sem_t*) lpCriticalSection->LockSemaphore);
#endif
}
VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
{
#if defined __APPLE__
semaphore_destroy(mach_task_self(), *((winpr_sem_t*) lpCriticalSection->LockSemaphore));
#else
sem_destroy((winpr_sem_t*) lpCriticalSection->LockSemaphore);
#endif
}
#endif

View File

@ -35,6 +35,8 @@
#include <unistd.h>
#endif
CRITICAL_SECTION cs = { NULL, 0, 0, NULL, NULL, 0 };
HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName)
{
WINPR_EVENT* event;
@ -64,6 +66,9 @@ HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
handle = winpr_Handle_Insert(HANDLE_TYPE_EVENT, event);
}
if (!cs.LockSemaphore)
InitializeCriticalSection(&cs);
return handle;
}
@ -97,22 +102,33 @@ BOOL SetEvent(HANDLE hEvent)
ULONG Type;
PVOID Object;
int length;
BOOL status;
WINPR_EVENT* event;
if (!winpr_Handle_GetInfo(hEvent, &Type, &Object))
return FALSE;
status = FALSE;
event = (WINPR_EVENT*) Object;
EnterCriticalSection(&cs);
if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
return TRUE;
if (winpr_Handle_GetInfo(hEvent, &Type, &Object))
{
event = (WINPR_EVENT*) Object;
length = write(event->pipe_fd[1], "-", 1);
if (!(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0))
{
length = write(event->pipe_fd[1], "-", 1);
if (length != 1)
return FALSE;
if (length == 1)
status = TRUE;
}
else
{
status = TRUE;
}
}
return TRUE;
LeaveCriticalSection(&cs);
return status;
}
BOOL ResetEvent(HANDLE hEvent)
@ -120,22 +136,32 @@ BOOL ResetEvent(HANDLE hEvent)
ULONG Type;
PVOID Object;
int length;
BOOL status;
WINPR_EVENT* event;
if (!winpr_Handle_GetInfo(hEvent, &Type, &Object))
return FALSE;
status = FALSE;
event = (WINPR_EVENT*) Object;
EnterCriticalSection(&cs);
while (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
if (winpr_Handle_GetInfo(hEvent, &Type, &Object))
{
length = read(event->pipe_fd[0], &length, 1);
event = (WINPR_EVENT*) Object;
if (length != 1)
return FALSE;
while (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
{
length = read(event->pipe_fd[0], &length, 1);
if (length == 1)
status = TRUE;
if (length != 1)
break;
}
}
return TRUE;
LeaveCriticalSection(&cs);
return status;
}
#endif

View File

@ -23,13 +23,6 @@
#include <winpr/synch.h>
/**
* InitOnceBeginInitialize
* InitOnceComplete
* InitOnceExecuteOnce
* InitOnceInitialize
*/
#ifndef _WIN32
BOOL InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL fPending, LPVOID* lpContext)