Skip to content

Commit

Permalink
Implemented thread handling for WaitForMultipleObjects.
Browse files Browse the repository at this point in the history
Implemented thread specific functions.
  • Loading branch information
Armin Novak authored and akallabeth committed Oct 27, 2014
1 parent 2de73e0 commit c304f45
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 99 deletions.
1 change: 1 addition & 0 deletions cmake/ConfigOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ option(WITH_DEBUG_SCARD "Print smartcard debug messages" ${DEFAULT_DEBUG_OPTION}
option(WITH_DEBUG_SND "Print rdpsnd debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_SVC "Print static virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_TRANSPORT "Print transport debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_THREADS "Print thread debug messages, enables handle dump" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_TIMEZONE "Print timezone debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_WND "Print window order debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_X11_CLIPRDR "Print X11 clipboard redirection debug messages" ${DEFAULT_DEBUG_OPTION})
Expand Down
1 change: 1 addition & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#cmakedefine WITH_DEBUG_SVC
#cmakedefine WITH_DEBUG_RDPEI
#cmakedefine WITH_DEBUG_TIMEZONE
#cmakedefine WITH_DEBUG_THREADS
#cmakedefine WITH_DEBUG_TRANSPORT
#cmakedefine WITH_DEBUG_WND
#cmakedefine WITH_DEBUG_X11
Expand Down
6 changes: 5 additions & 1 deletion winpr/include/winpr/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,11 @@ WINPR_API BOOL TlsFree(DWORD dwTlsIndex);

/* CommandLineToArgvA is not present in the original Windows API, WinPR always exports it */

WINPR_API LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs);
WINPR_API LPSTR *CommandLineToArgvA(LPCSTR lpCmdLine, int *pNumArgs);

#if defined(WITH_DEBUG_THREADS)
WINPR_API VOID DumpThreadHandles(void);
#endif

#ifdef __cplusplus
}
Expand Down
15 changes: 1 addition & 14 deletions winpr/libwinpr/handle/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,7 @@ BOOL CloseHandle(HANDLE hObject)

LeaveCriticalSection(&_HandleCloseCbsLock);

if (Type == HANDLE_TYPE_THREAD)
{
WINPR_THREAD* thread;
thread = (WINPR_THREAD*) Object;

if (thread->started)
{
pthread_detach(thread->thread);
}

free(thread);
return TRUE;
}
else if (Type == HANDLE_TYPE_PROCESS)
if (Type == HANDLE_TYPE_PROCESS)
{
WINPR_PROCESS* process;
process = (WINPR_PROCESS*) Object;
Expand Down
11 changes: 2 additions & 9 deletions winpr/libwinpr/pool/pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,13 @@ static void* thread_pool_work_func(void* arg)
}
}

ExitThread(0);
return NULL;
}

static void threads_close(void *thread)
{
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
}

Expand Down Expand Up @@ -184,15 +186,6 @@ VOID CloseThreadpool(PTP_POOL ptpp)

SetEvent(ptpp->TerminateEvent);

index = ArrayList_Count(ptpp->Threads) - 1;

while (index >= 0)
{
thread = (HANDLE) ArrayList_GetItem(ptpp->Threads, index);
WaitForSingleObject(thread, INFINITE);
index--;
}

ArrayList_Free(ptpp->Threads);
Queue_Free(ptpp->PendingQueue);
CountdownEvent_Free(ptpp->WorkComplete);
Expand Down
118 changes: 57 additions & 61 deletions winpr/libwinpr/synch/wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,33 +107,6 @@ static long long ts_difftime(const struct timespec* o,
return newValue - oldValue;
}

static int pthread_timedjoin_np(pthread_t td, void** res,
struct timespec* timeout)
{
struct timespec timenow;
struct timespec sleepytime;
/* This is just to avoid a completely busy wait */
sleepytime.tv_sec = 0;
sleepytime.tv_nsec = 10000000; /* 10ms */

do
{
if (pthread_kill(td, 0))
return pthread_join(td, res);

nanosleep(&sleepytime, NULL);
clock_gettime(CLOCK_MONOTONIC, &timenow);

if (ts_difftime(timeout, &timenow) >= 0)
{
return ETIMEDOUT;
}
}
while (TRUE);

return ETIMEDOUT;
}

#if defined(__FreeBSD__)
/*the only way to get it work is to remove the static*/
int pthread_mutex_timedlock(pthread_mutex_t* mutex, const struct timespec* timeout)
Expand All @@ -143,10 +116,13 @@ static int pthread_mutex_timedlock(pthread_mutex_t* mutex, const struct timespec
{
struct timespec timenow;
struct timespec sleepytime;
unsigned long long diff;
int retcode;
/* This is just to avoid a completely busy wait */
sleepytime.tv_sec = 0;
sleepytime.tv_nsec = 10000000; /* 10ms */
clock_gettime(CLOCK_MONOTONIC, &timenow);
diff = ts_difftime(&timenow, timeout);
sleepytime.tv_sec = diff / 1000000000LL;
sleepytime.tv_nsec = diff % 1000000000LL;

while ((retcode = pthread_mutex_trylock(mutex)) == EBUSY)
{
Expand Down Expand Up @@ -223,43 +199,30 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)

if (Type == HANDLE_TYPE_THREAD)
{
int status = 0;
WINPR_THREAD* thread;
void* thread_status = NULL;
thread = (WINPR_THREAD*) Object;
void *thread_status;
int status;
WINPR_THREAD *thread = (WINPR_THREAD *)Object;
status = waitOnFd(thread->pipe_fd[0], dwMilliseconds);

if (thread->started)
if (status < 0)
{
if (dwMilliseconds != INFINITE)
{
struct timespec timeout;

/* pthread_timedjoin_np returns ETIMEDOUT in case the timeout is 0,
* so set it to the smallest value to get a proper return value. */
if (dwMilliseconds == 0)
dwMilliseconds ++;

clock_gettime(CLOCK_MONOTONIC, &timeout);
ts_add_ms(&timeout, dwMilliseconds);
status = pthread_timedjoin_np(thread->thread, &thread_status, &timeout);

if (ETIMEDOUT == status)
return WAIT_TIMEOUT;
}
else
status = pthread_join(thread->thread, &thread_status);

thread->started = FALSE;
WLog_ERR(TAG, "waitOnFd() failure [%d] %s", errno, strerror(errno));
return WAIT_FAILED;
}
>
if (status != 1)
return WAIT_TIMEOUT;

if (status != 0)
{
WLog_ERR(TAG, "pthread_join failure: [%d] %s",
status, strerror(status));
}
status = pthread_join(thread->thread, &thread_status);

if (thread_status)
thread->dwExitCode = ((DWORD)(size_t) thread_status);
if (status != 0)
{
WLog_ERR(TAG, "pthread_join failure: [%d] %s",
status, strerror(status));
}

if (thread_status)
thread->dwExitCode = ((DWORD)(size_t) thread_status);
}
else if (Type == HANDLE_TYPE_PROCESS)
{
Expand Down Expand Up @@ -517,6 +480,17 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
return WAIT_FAILED;
}
}
else if (Type == HANDLE_TYPE_THREAD)
{
WINPR_THREAD *thread = (WINPR_THREAD *) Object;
fd = thread->pipe_fd[0];

if (fd == -1)
{
WLog_ERR(TAG, "invalid thread file descriptor");
return WAIT_FAILED;
}
}
else if (Type == HANDLE_TYPE_NAMED_PIPE)
{
WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object;
Expand Down Expand Up @@ -604,6 +578,11 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
WINPR_TIMER* timer = (WINPR_TIMER*) Object;
fd = timer->fd;
}
else if (Type == HANDLE_TYPE_THREAD)
{
WINPR_THREAD *thread = (WINPR_THREAD *) Object;
fd = thread->pipe_fd[0];
}
else if (Type == HANDLE_TYPE_NAMED_PIPE)
{
WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object;
Expand Down Expand Up @@ -651,6 +630,23 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
return WAIT_FAILED;
}
}
else if (Type == HANDLE_TYPE_THREAD)
{
void *thread_status;
int status;
WINPR_THREAD *thread = (WINPR_THREAD *)Object;
status = pthread_join(thread->thread, &thread_status);

if (status != 0)
{
WLog_ERR(TAG, " pthread_join failure: [%d] %s",
status, strerror(status));
return WAIT_FAILED;
}

if (thread_status)
thread->dwExitCode = ((DWORD)(size_t) thread_status);
}

return (WAIT_OBJECT_0 + index);
}
Expand Down
Loading

0 comments on commit c304f45

Please sign in to comment.