Merge pull request #1460 from akallabeth/thread_handle_fixes

Thread handle fixes
This commit is contained in:
Marc-André Moreau 2013-09-16 13:40:32 -07:00
commit 336e47e82f
14 changed files with 201 additions and 40 deletions

View File

@ -419,7 +419,9 @@ static BOOL audin_server_close(audin_server_context* context)
SetEvent(audin->stopEvent);
WaitForSingleObject(audin->thread, INFINITE);
CloseHandle(audin->thread);
CloseHandle(audin->stopEvent);
audin->thread = NULL;
audin->stopEvent = NULL;
}
if (audin->audin_channel)

View File

@ -631,8 +631,9 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve
/**
* called only from main thread
*/
static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
{
int rc = TRUE;
wMessage message;
wMessage* event;
rdpChannel* channel;
@ -642,7 +643,10 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan
while (MessageQueue_Peek(channels->MsgPipe->Out, &message, TRUE))
{
if (message.id == WMQ_QUIT)
{
rc = FALSE;
break;
}
if (message.id == 0)
{
@ -677,6 +681,8 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan
*/
}
}
return rc;
}
/**
@ -730,7 +736,7 @@ int freerdp_channels_process_pending_messages(freerdp* instance)
if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0)
{
freerdp_channels_process_sync(channels, instance);
return freerdp_channels_process_sync(channels, instance);
}
return TRUE;
@ -782,4 +788,7 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
if (pChannelClientData->pChannelInitEventProc)
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_TERMINATED, 0, 0);
}
/* Emit a quit signal to the internal message pipe. */
MessagePipe_PostQuit(channels->MsgPipe, 0);
}

View File

@ -633,17 +633,18 @@ static void drive_process_irp_list(DRIVE_DEVICE* disk)
static void* drive_thread_func(void* arg)
{
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) arg;
HANDLE hdl[] = {disk->irpEvent, disk->stopEvent};
while (1)
{
WaitForSingleObject(disk->irpEvent, INFINITE);
if (WaitForSingleObject(disk->stopEvent, 0) == WAIT_OBJECT_0)
DWORD rc = WaitForMultipleObjects(2, hdl, FALSE, INFINITE);
if (rc == WAIT_OBJECT_0 + 1)
break;
ResetEvent(disk->irpEvent);
drive_process_irp_list(disk);
}
ExitThread(0);
return NULL;
}
@ -664,8 +665,10 @@ static void drive_free(DEVICE* device)
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;
SetEvent(disk->stopEvent);
WaitForSingleObject(disk->thread, INFINITE);
CloseHandle(disk->thread);
CloseHandle(disk->irpEvent);
CloseHandle(disk->stopEvent);
while ((irp = (IRP*) InterlockedPopEntrySList(disk->pIrpList)) != NULL)
irp->Discard(irp);

View File

@ -200,6 +200,8 @@ static void* printer_thread_func(void* arg)
printer_process_irp(printer_dev, irp);
}
ExitThread(0);
return NULL;
}
@ -219,11 +221,14 @@ static void printer_free(DEVICE* device)
SetEvent(printer_dev->stopEvent);
WaitForSingleObject(printer_dev->thread, INFINITE);
CloseHandle(printer_dev->thread);
while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
irp->Discard(irp);
CloseHandle(printer_dev->thread);
CloseHandle(printer_dev->stopEvent);
CloseHandle(printer_dev->event);
_aligned_free(printer_dev->pIrpList);
if (printer_dev->printer)

View File

@ -21,6 +21,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -97,6 +98,7 @@ struct _RDPEI_PLUGIN
RDPINPUT_CONTACT_POINT* contactPoints;
HANDLE event;
HANDLE stopEvent;
HANDLE thread;
CRITICAL_SECTION lock;
@ -156,10 +158,16 @@ static void* rdpei_schedule_thread(void* arg)
DWORD status;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg;
RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface;
HANDLE hdl[] = {rdpei->event, rdpei->stopEvent};
assert(NULL != rdpei);
assert(NULL != context);
while (1)
{
status = WaitForSingleObject(rdpei->event, 20);
status = WaitForMultipleObjects(2, hdl, FALSE, 20);
if (status == WAIT_OBJECT_0 + 1)
break;
EnterCriticalSection(&rdpei->lock);
@ -174,6 +182,8 @@ static void* rdpei_schedule_thread(void* arg)
LeaveCriticalSection(&rdpei->lock);
}
ExitThread(0);
return NULL;
}
@ -218,13 +228,6 @@ int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
Stream_SealLength(s);
if (!rdpei->thread)
{
InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpei_schedule_thread, (void*) rdpei, 0, NULL);
}
status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength);
Stream_Free(s, TRUE);
@ -488,6 +491,12 @@ static int rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
rdpei->listener->pInterface = rdpei->iface.pInterface;
InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
rdpei_schedule_thread, (void*) rdpei, 0, NULL);
return status;
}
@ -497,6 +506,22 @@ static int rdpei_plugin_terminated(IWTSPlugin* pPlugin)
DEBUG_DVC("");
assert(NULL != pPlugin);
SetEvent(rdpei->stopEvent);
EnterCriticalSection(&rdpei->lock);
WaitForSingleObject(rdpei->thread, INFINITE);
CloseHandle(rdpei->stopEvent);
CloseHandle(rdpei->event);
CloseHandle(rdpei->thread);
DeleteCriticalSection(&rdpei->lock);
if (rdpei->listener_callback)
free(rdpei->listener_callback);
free(rdpei);
return 0;

View File

@ -541,6 +541,9 @@ void rdpsnd_server_context_free(rdpsnd_server_context* context)
SetEvent(rdpsnd->StopEvent);
WaitForSingleObject(rdpsnd->thread, INFINITE);
CloseHandle(rdpsnd->StopEvent);
CloseHandle(rdpsnd->thread);
if (rdpsnd->rdpsnd_channel)
WTSVirtualChannelClose(rdpsnd->rdpsnd_channel);

View File

@ -22,6 +22,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -346,6 +347,7 @@ void* serial_thread_mfunc(void* arg)
{
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
assert(NULL != serial);
while(1)
{
int sl;
@ -366,6 +368,7 @@ void* serial_thread_mfunc(void* arg)
}
}
ExitThread(0);
return NULL;
}
@ -376,6 +379,7 @@ static void* serial_thread_func(void* arg)
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue), serial->newEvent};
assert(NULL != serial);
while (1)
{
status = WaitForMultipleObjects(3, ev, FALSE, INFINITE);
@ -401,6 +405,7 @@ static void* serial_thread_func(void* arg)
serial_check_fds(serial);
}
ExitThread(0);
return NULL;
}

View File

@ -112,13 +112,16 @@ struct _SMARTCARD_IRP_WORKER
};
typedef struct _SMARTCARD_IRP_WORKER SMARTCARD_IRP_WORKER;
static void smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
static void *smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
{
smartcard_process_irp(irpWorker->smartcard, irpWorker->irp);
CloseHandle(irpWorker->thread);
free(irpWorker);
ExitThread(0);
return NULL;
}
static void* smartcard_thread_func(void* arg)

View File

@ -569,7 +569,10 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
rdpChannels* channels;
instance = (freerdp*) lpParam;
assert(NULL != instance);
wfc = (wfContext*) instance->context;
assert(NULL != wfc);
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
@ -690,13 +693,13 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
}
/* cleanup */
wfc->mainThreadId = 0;
freerdp_channels_close(channels, instance);
freerdp_disconnect(instance);
printf("Main thread exited.\n");
ExitThread(0);
return 0;
}
@ -708,6 +711,7 @@ DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
HHOOK hook_handle;
wfc = (wfContext*) lpParam;
assert(NULL != wfc);
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, wfc->hInstance, 0);
@ -734,9 +738,9 @@ DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
fprintf(stderr, "failed to install keyboard hook\n");
}
wfc->keyboardThreadId = 0;
printf("Keyboard thread exited.\n");
ExitThread(0);
return (DWORD) NULL;
}
@ -1078,12 +1082,27 @@ int wfreerdp_client_stop(rdpContext* context)
{
wfContext* wfc = (wfContext*) context;
if (wfc->mainThreadId)
if (wfc->thread)
{
PostThreadMessage(wfc->mainThreadId, WM_QUIT, 0, 0);
if (wfc->keyboardThreadId)
WaitForSingleObject(wfc->thread, INFINITE);
CloseHandle(wfc->thread);
wfc->thread = NULL;
wfc->mainThreadId = 0;
}
if (wfc->keyboardThread)
{
PostThreadMessage(wfc->keyboardThreadId, WM_QUIT, 0, 0);
WaitForSingleObject(wfc->keyboardThread, INFINITE);
CloseHandle(wfc->keyboardThread);
wfc->keyboardThread = NULL;
wfc->keyboardThreadId = 0;
}
return 0;
}

View File

@ -773,12 +773,12 @@ BOOL xf_pre_connect(freerdp* instance)
if (settings->Username == NULL)
{
fprintf(stderr, "--authonly, but no -u username. Please provide one.\n");
exit(1);
return FALSE;
}
if (settings->Password == NULL)
{
fprintf(stderr, "--authonly, but no -p password. Please provide one.\n");
exit(1);
return FALSE;
}
fprintf(stderr, "%s:%d: Authentication only. Don't connect to X.\n", __FILE__, __LINE__);
/* Avoid XWindows initialization and configuration below. */
@ -1224,6 +1224,8 @@ void* xf_update_thread(void* arg)
wMessageQueue* queue;
freerdp* instance = (freerdp*) arg;
assert( NULL != instance);
status = 1;
queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
@ -1241,6 +1243,7 @@ void* xf_update_thread(void* arg)
break;
}
ExitThread(0);
return NULL;
}
@ -1253,9 +1256,12 @@ void* xf_input_thread(void* arg)
int pending_status = 1;
int process_status = 1;
freerdp* instance = (freerdp*) arg;
assert(NULL != instance);
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds);
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
@ -1288,9 +1294,8 @@ void* xf_input_thread(void* arg)
break;
}
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
MessageQueue_PostQuit(queue, 0);
ExitThread(0);
return NULL;
}
@ -1301,8 +1306,10 @@ void* xf_channels_thread(void* arg)
HANDLE event;
rdpChannels* channels;
freerdp* instance = (freerdp*) arg;
assert(NULL != instance);
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
channels = instance->context->channels;
event = freerdp_channels_get_event_handle(instance);
@ -1310,9 +1317,13 @@ void* xf_channels_thread(void* arg)
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
status = freerdp_channels_process_pending_messages(instance);
if (!status)
break;
xf_process_channel_event(channels, instance);
}
ExitThread(0);
return NULL;
}
@ -1356,6 +1367,7 @@ void* xf_thread(void* param)
input_event = NULL;
instance = (freerdp*) param;
assert(NULL != instance);
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
@ -1364,6 +1376,7 @@ void* xf_thread(void* param)
status = freerdp_connect(instance);
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
/* Connection succeeded. --authonly ? */
if (instance->settings->AuthenticationOnly)
@ -1533,6 +1546,10 @@ void* xf_thread(void* param)
}
}
/* Close the channels first. This will signal the internal message pipes
* that the threads should quit. */
freerdp_channels_close(channels, instance);
if (async_update)
{
wMessageQueue* update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
@ -1541,6 +1558,20 @@ void* xf_thread(void* param)
CloseHandle(update_thread);
}
if (async_input)
{
wMessageQueue* input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
MessageQueue_PostQuit(input_queue, 0);
WaitForSingleObject(input_thread, INFINITE);
CloseHandle(input_thread);
}
if (async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
FILE* fin = fopen("/tmp/tsmf.tid", "rt");
if (fin)
@ -1577,7 +1608,6 @@ void* xf_thread(void* param)
if (!exit_code)
exit_code = freerdp_error_info(instance);
freerdp_channels_close(channels, instance);
freerdp_channels_free(channels);
freerdp_disconnect(instance);
gdi_free(instance);
@ -1713,7 +1743,8 @@ static int xfreerdp_client_start(rdpContext* context)
return -1;
}
xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_thread, context->instance, 0, NULL);
xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_thread,
context->instance, 0, NULL);
return 0;
}
@ -1722,6 +1753,7 @@ static int xfreerdp_client_stop(rdpContext* context)
{
xfContext* xfc = (xfContext*) context;
assert(NULL != context);
if (context->settings->AsyncInput)
{
wMessageQueue* queue;
@ -1735,8 +1767,11 @@ static int xfreerdp_client_stop(rdpContext* context)
xfc->disconnect = TRUE;
}
WaitForSingleObject(xfc->thread, INFINITE);
if (xfc->thread)
{
CloseHandle(xfc->thread);
xfc->thread = NULL;
}
return 0;
}

View File

@ -21,6 +21,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -85,6 +86,14 @@ BOOL transport_disconnect(rdpTransport* transport)
status &= tcp_disconnect(transport->TcpIn);
}
if (transport->async)
{
SetEvent(transport->stopEvent);
WaitForSingleObject(transport->thread, INFINITE);
CloseHandle(transport->thread);
CloseHandle(transport->stopEvent);
}
return status;
}
@ -793,8 +802,14 @@ static void* transport_client_thread(void* arg)
rdpTransport* transport;
transport = (rdpTransport*) arg;
assert(NULL != transport);
assert(NULL != transport->settings);
instance = (freerdp*) transport->settings->instance;
assert(NULL != instance);
context = instance->context;
assert(NULL != instance->context);
while (1)
{
@ -803,25 +818,20 @@ static void* transport_client_thread(void* arg)
events[nCount] = transport->connectedEvent;
status = WaitForMultipleObjects(nCount + 1, events, FALSE, INFINITE);
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
{
if (status == WAIT_OBJECT_0)
break;
}
transport_get_read_handles(transport, (HANDLE*) &events, &nCount);
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
{
if (status == WAIT_OBJECT_0)
break;
}
if (!freerdp_check_fds(instance))
break;
}
ExitThread(0);
return NULL;
}

View File

@ -22,6 +22,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -185,6 +186,8 @@ static void* svc_plugin_thread_func(void* arg)
DEBUG_SVC("in");
assert(NULL != plugin);
IFCALL(plugin->connect_callback, plugin);
while (1)
@ -212,6 +215,8 @@ static void* svc_plugin_thread_func(void* arg)
DEBUG_SVC("out");
ExitThread(0);
return 0;
}

View File

@ -17,6 +17,7 @@
* limitations under the License.
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -92,7 +93,7 @@ void* xf_server_thread(void* param)
}
}
listener->Close(listener);
ExitThread(0);
return NULL;
}
@ -114,9 +115,13 @@ int freerdp_server_global_uninit()
int freerdp_server_start(xfServer* server)
{
assert(NULL != server);
server->thread = NULL;
if (server->listener->Open(server->listener, NULL, 3389))
{
server->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_server_thread, (void*) server, 0, NULL);
server->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
xf_server_thread, (void*) server, 0, NULL);
}
return 0;
@ -124,6 +129,17 @@ int freerdp_server_start(xfServer* server)
int freerdp_server_stop(xfServer* server)
{
if (server->thread)
{
/* ATTENTION: Terminate thread kills a thread, assure
* no resources are allocated during thread execution,
* as they will not be freed! */
TerminateThread(server->thread, 0);
WaitForSingleObject(server->thread, INFINITE);
CloseHandle(server->thread);
server->listener->Close(server->listener);
}
return 0;
}

View File

@ -21,6 +21,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -175,6 +176,17 @@ int xf_xshm_init(xfInfo* xfi)
return 0;
}
void xf_info_free(xfInfo *info)
{
assert(NULL != info);
if (info->display)
XCloseDisplay(info->display);
freerdp_clrconv_free(info->clrconv);
free(info);
}
xfInfo* xf_info_init()
{
int i;
@ -313,6 +325,11 @@ void xf_peer_context_free(freerdp_peer* client, xfPeerContext* context)
{
if (context)
{
xf_info_free(context->info);
CloseHandle(context->updateReadyEvent);
CloseHandle(context->updateSentEvent);
Stream_Free(context->s, TRUE);
rfx_context_free(context->rfx_context);
}
@ -508,6 +525,8 @@ static void* xf_peer_main_loop(void* arg)
struct timeval timeout;
freerdp_peer* client = (freerdp_peer*) arg;
assert(NULL != client);
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(&timeout, sizeof(struct timeval));
@ -598,6 +617,8 @@ static void* xf_peer_main_loop(void* arg)
freerdp_peer_context_free(client);
freerdp_peer_free(client);
ExitThread(0);
return NULL;
}