libwinpr-thread: fix non-blocking internal pipe-based event on OS X

This commit is contained in:
Marc-André Moreau 2014-11-20 11:48:02 -05:00
parent 4fbec7633a
commit 2afcac7838

View File

@ -83,6 +83,7 @@
#include <winpr/debug.h>
#include <errno.h>
#include <fcntl.h>
#include <winpr/collections.h>
@ -95,14 +96,14 @@
static pthread_once_t thread_initialized = PTHREAD_ONCE_INIT;
static HANDLE_CLOSE_CB _ThreadHandleCloseCb;
static wListDictionary *thread_list = NULL;
static wListDictionary* thread_list = NULL;
static BOOL ThreadCloseHandle(HANDLE handle);
static void cleanup_handle(void *obj);
static void cleanup_handle(void* obj);
static BOOL ThreadIsHandled(HANDLE handle)
{
WINPR_THREAD *pThread = (WINPR_THREAD *)handle;
WINPR_THREAD* pThread = (WINPR_THREAD*) handle;
if (!pThread || pThread->Type != HANDLE_TYPE_THREAD)
{
@ -113,7 +114,6 @@ static BOOL ThreadIsHandled(HANDLE handle)
return TRUE;
}
static void ThreadInitialize(void)
{
_ThreadHandleCloseCb.IsHandled = ThreadIsHandled;
@ -130,7 +130,7 @@ static void dump_thread(WINPR_THREAD* thread)
WLog_DBG(TAG, "Called from:");
msg = winpr_backtrace_symbols(stack, &used);
for (i=0; i<used; i++)
for (i = 0; i < used; i++)
WLog_DBG(TAG, "[%d]: %s", i, msg[i]);
free(msg);
@ -138,26 +138,29 @@ static void dump_thread(WINPR_THREAD* thread)
WLog_DBG(TAG, "Thread handle created still not closed!");
msg = winpr_backtrace_symbols(thread->create_stack, &used);
for (i=0; i<used; i++)
for (i = 0; i < used; i++)
WLog_DBG(TAG, "[%d]: %s", i, msg[i]);
free(msg);
if (thread->started)
{
WLog_DBG(TAG, "Thread still running!");
}
else if (!thread->exit_stack)
{
WLog_DBG(TAG, "Thread suspended.");
}
else
{
WLog_DBG(TAG, "Thread exited at:");
msg = winpr_backtrace_symbols(thread->exit_stack, &used);
for (i=0; i<used; i++)
for (i = 0; i < used; i++)
WLog_DBG(TAG, "[%d]: %s", i, msg[i]);
free(msg);
}
#endif
}
@ -180,7 +183,6 @@ static BOOL set_event(WINPR_THREAD *thread)
status = (length == 0) ? TRUE : FALSE;
#else
if (WaitForSingleObject(thread, 0) != WAIT_OBJECT_0)
{
length = write(thread->pipe_fd[1], "-", 1);
@ -192,7 +194,6 @@ static BOOL set_event(WINPR_THREAD *thread)
{
status = TRUE;
}
#endif
return status;
}
@ -223,21 +224,21 @@ static BOOL reset_event(WINPR_THREAD *thread)
return status;
}
static int thread_compare(void *a, void *b)
static BOOL thread_compare(void* a, void* b)
{
pthread_t *p1 = a;
pthread_t *p2 = b;
int rc = pthread_equal(*p1, *p2);
pthread_t* p1 = a;
pthread_t* p2 = b;
BOOL rc = pthread_equal(*p1, *p2);
return rc;
}
/* Thread launcher function responsible for registering
* cleanup handlers and calling pthread_exit, if not done
* in thread function. */
static void *thread_launcher(void *arg)
static void* thread_launcher(void* arg)
{
void *rc = NULL;
WINPR_THREAD *thread = (WINPR_THREAD *)arg;
void* rc = NULL;
WINPR_THREAD* thread = (WINPR_THREAD*) arg;
if (!thread)
{
@ -246,7 +247,7 @@ static void *thread_launcher(void *arg)
}
else
{
void *(*fkt)(void *) = (void *)thread->lpStartAddress;
void *(*fkt)(void*) = (void*) thread->lpStartAddress;
if (!fkt)
{
@ -291,9 +292,10 @@ static void winpr_StartThread(WINPR_THREAD *thread)
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
int flags;
HANDLE handle;
WINPR_THREAD *thread;
thread = (WINPR_THREAD *) calloc(1, sizeof(WINPR_THREAD));
WINPR_THREAD* thread;
thread = (WINPR_THREAD*) calloc(1, sizeof(WINPR_THREAD));
if (!thread)
return NULL;
@ -303,10 +305,12 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize
thread->lpParameter = lpParameter;
thread->lpStartAddress = lpStartAddress;
thread->lpThreadAttributes = lpThreadAttributes;
#if defined(WITH_DEBUG_THREADS)
thread->create_stack = winpr_backtrace(20);
dump_thread(thread);
#endif
#ifdef HAVE_EVENTFD_H
thread->pipe_fd[0] = eventfd(0, EFD_NONBLOCK);
@ -316,9 +320,7 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize
free(thread);
return NULL;
}
#else
if (pipe(thread->pipe_fd) < 0)
{
WLog_ERR(TAG, "failed to create thread");
@ -326,12 +328,15 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize
return NULL;
}
flags = fcntl(thread->pipe_fd[0], F_GETFL);
fcntl(thread->pipe_fd[0], F_SETFL, flags | O_NONBLOCK);
#endif
pthread_mutex_init(&thread->mutex, 0);
WINPR_HANDLE_SET_TYPE(thread, HANDLE_TYPE_THREAD);
handle = (HANDLE) thread;
if (NULL == thread_list)
if (!thread_list)
{
thread_list = ListDictionary_New(TRUE);
thread_list->objectKey.fnObjectEquals = thread_compare;
@ -347,7 +352,7 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize
void cleanup_handle(void *obj)
{
WINPR_THREAD *thread = (WINPR_THREAD *)obj;
WINPR_THREAD* thread = (WINPR_THREAD*) obj;
int rc = pthread_mutex_destroy(&thread->mutex);
if (rc)
@ -377,7 +382,7 @@ void cleanup_handle(void *obj)
BOOL ThreadCloseHandle(HANDLE handle)
{
WINPR_THREAD *thread = (WINPR_THREAD *)handle;
WINPR_THREAD* thread = (WINPR_THREAD*) handle;
if (!thread_list)
{
@ -401,7 +406,9 @@ BOOL ThreadCloseHandle(HANDLE handle)
pthread_detach(thread->thread);
}
else
{
cleanup_handle(thread);
}
ListDictionary_Unlock(thread_list);
@ -469,12 +476,12 @@ BOOL GetExitCodeThread(HANDLE hThread, LPDWORD lpExitCode)
{
ULONG Type;
PVOID Object;
WINPR_THREAD *thread;
WINPR_THREAD* thread;
if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
return FALSE;
thread = (WINPR_THREAD *) Object;
thread = (WINPR_THREAD*) Object;
*lpExitCode = thread->dwExitCode;
return TRUE;
}
@ -484,7 +491,7 @@ HANDLE _GetCurrentThread(VOID)
HANDLE hdl = NULL;
pthread_t tid = pthread_self();
if (NULL == thread_list)
if (!thread_list)
{
WLog_ERR(TAG, "function called without existing thread list!");
#if defined(WITH_DEBUG_THREADS)
@ -522,7 +529,7 @@ DWORD ResumeThread(HANDLE hThread)
if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
return 0;
thread = (WINPR_THREAD *) Object;
thread = (WINPR_THREAD*) Object;
pthread_mutex_lock(&thread->mutex);
if (!thread->started)
@ -549,12 +556,12 @@ BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode)
{
ULONG Type;
PVOID Object;
WINPR_THREAD *thread;
WINPR_THREAD* thread;
if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
return 0;
thread = (WINPR_THREAD *) Object;
thread = (WINPR_THREAD*) Object;
thread->exited = TRUE;
thread->dwExitCode = dwExitCode;
pthread_mutex_lock(&thread->mutex);
@ -576,15 +583,19 @@ VOID DumpThreadHandles(void)
WLog_DBG(TAG, "---------------- Called from ----------------------------");
msg = winpr_backtrace_symbols(stack, &used);
for (i=0; i<used; i++)
for (i = 0; i < used; i++)
{
WLog_DBG(TAG, "[%d]: %s", i, msg[i]);
}
free(msg);
winpr_backtrace_free(stack);
WLog_DBG(TAG, "---------------- Start Dumping thread handles -----------");
if (!thread_list)
{
WLog_DBG(TAG, "All threads properly shut down and disposed of.");
}
else
{
ULONG_PTR *keys = NULL;
@ -592,19 +603,23 @@ VOID DumpThreadHandles(void)
int x, count = ListDictionary_GetKeys(thread_list, &keys);
WLog_DBG(TAG, "Dumping %d elements\n", count);
for (x=0; x<count; x++)
for (x = 0; x < count; x++)
{
WINPR_THREAD* thread = ListDictionary_GetItemValue(thread_list, (void*)keys[x]);
WINPR_THREAD* thread = ListDictionary_GetItemValue(thread_list, (void*) keys[x]);
WLog_DBG(TAG, "Thread [%d] handle created still not closed!", x);
msg = winpr_backtrace_symbols(thread->create_stack, &used);
for (i=0; i<used; i++)
for (i = 0; i < used; i++)
{
WLog_DBG(TAG, "[%d]: %s", i, msg[i]);
}
free(msg);
if (thread->started)
{
WLog_DBG(TAG, "Thread [%d] still running!", x);
}
else
{
WLog_DBG(TAG, "Thread [%d] exited at:", x);