Merge pull request #1429 from master
This commit is contained in:
commit
ec6b84fde4
@ -63,7 +63,9 @@ struct _SERIAL_DEVICE
|
|||||||
SERIAL_TTY* tty;
|
SERIAL_TTY* tty;
|
||||||
|
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
|
HANDLE mthread;
|
||||||
HANDLE stopEvent;
|
HANDLE stopEvent;
|
||||||
|
HANDLE newEvent;
|
||||||
|
|
||||||
wQueue* queue;
|
wQueue* queue;
|
||||||
LIST* pending_irps;
|
LIST* pending_irps;
|
||||||
@ -80,6 +82,7 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32
|
|||||||
static void serial_check_for_events(SERIAL_DEVICE* serial);
|
static void serial_check_for_events(SERIAL_DEVICE* serial);
|
||||||
static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp);
|
static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp);
|
||||||
static BOOL serial_check_fds(SERIAL_DEVICE* serial);
|
static BOOL serial_check_fds(SERIAL_DEVICE* serial);
|
||||||
|
static void* serial_thread_mfunc(void* arg);
|
||||||
|
|
||||||
static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||||
{
|
{
|
||||||
@ -113,6 +116,18 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
serial->tty = tty;
|
serial->tty = tty;
|
||||||
|
|
||||||
|
serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE,
|
||||||
|
STATUS_CANCELLED);
|
||||||
|
serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ,
|
||||||
|
STATUS_CANCELLED);
|
||||||
|
serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE,
|
||||||
|
STATUS_CANCELLED);
|
||||||
|
|
||||||
|
serial->mthread = CreateThread(NULL, 0,
|
||||||
|
(LPTHREAD_START_ROUTINE) serial_thread_mfunc, (void*) serial,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
DEBUG_SVC("%s(%d) created.", serial->path, FileId);
|
DEBUG_SVC("%s(%d) created.", serial->path, FileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +154,11 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
|
|||||||
{
|
{
|
||||||
DEBUG_SVC("%s(%d) closed.", serial->path, tty->id);
|
DEBUG_SVC("%s(%d) closed.", serial->path, tty->id);
|
||||||
|
|
||||||
|
TerminateThread(serial->mthread, 0);
|
||||||
|
WaitForSingleObject(serial->mthread, INFINITE);
|
||||||
|
CloseHandle(serial->mthread);
|
||||||
|
serial->mthread = NULL;
|
||||||
|
|
||||||
serial_tty_free(tty);
|
serial_tty_free(tty);
|
||||||
serial->tty = NULL;
|
serial->tty = NULL;
|
||||||
}
|
}
|
||||||
@ -318,36 +338,67 @@ static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
|
|||||||
serial_check_for_events(serial);
|
serial_check_for_events(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This thread is used as a workaround for the missing serial event
|
||||||
|
* support in WaitForMultipleObjects.
|
||||||
|
* It monitors the terminal for events and posts it in a supported
|
||||||
|
* form that WaitForMultipleObjects can use it. */
|
||||||
|
void* serial_thread_mfunc(void* arg)
|
||||||
|
{
|
||||||
|
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
int sl;
|
||||||
|
fd_set rd;
|
||||||
|
|
||||||
|
if(!serial->tty || serial->tty->fd <= 0)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Monitor thread still running, but no terminal opened!");
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FD_ZERO(&rd);
|
||||||
|
FD_SET(serial->tty->fd, &rd);
|
||||||
|
sl = select(serial->tty->fd + 1, &rd, NULL, NULL, NULL);
|
||||||
|
if( sl > 0 )
|
||||||
|
SetEvent(serial->newEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void* serial_thread_func(void* arg)
|
static void* serial_thread_func(void* arg)
|
||||||
{
|
{
|
||||||
IRP* irp;
|
IRP* irp;
|
||||||
DWORD status;
|
DWORD status;
|
||||||
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
|
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
|
||||||
HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue)};
|
HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue), serial->newEvent};
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
status = WaitForMultipleObjects(2, ev, FALSE, 1);
|
status = WaitForMultipleObjects(3, ev, FALSE, INFINITE);
|
||||||
|
|
||||||
if (WAIT_OBJECT_0 == status)
|
if (WAIT_OBJECT_0 == status)
|
||||||
break;
|
break;
|
||||||
|
else if (status == WAIT_OBJECT_0 + 1)
|
||||||
serial->nfds = 1;
|
|
||||||
FD_ZERO(&serial->read_fds);
|
|
||||||
FD_ZERO(&serial->write_fds);
|
|
||||||
|
|
||||||
serial->tv.tv_sec = 0;
|
|
||||||
serial->tv.tv_usec = 0;
|
|
||||||
serial->select_timeout = 0;
|
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0 + 1)
|
|
||||||
{
|
{
|
||||||
|
FD_ZERO(&serial->read_fds);
|
||||||
|
FD_ZERO(&serial->write_fds);
|
||||||
|
|
||||||
|
serial->tv.tv_sec = 0;
|
||||||
|
serial->tv.tv_usec = 0;
|
||||||
|
serial->select_timeout = 0;
|
||||||
|
|
||||||
if ((irp = (IRP*) Queue_Dequeue(serial->queue)))
|
if ((irp = (IRP*) Queue_Dequeue(serial->queue)))
|
||||||
serial_process_irp(serial, irp);
|
serial_process_irp(serial, irp);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else if (status == WAIT_OBJECT_0 + 2)
|
||||||
|
ResetEvent(serial->newEvent);
|
||||||
|
|
||||||
serial_check_fds(serial);
|
if(serial->tty)
|
||||||
|
serial_check_fds(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -368,6 +419,12 @@ static void serial_free(DEVICE* device)
|
|||||||
|
|
||||||
/* Stop thread */
|
/* Stop thread */
|
||||||
SetEvent(serial->stopEvent);
|
SetEvent(serial->stopEvent);
|
||||||
|
if(serial->mthread)
|
||||||
|
{
|
||||||
|
TerminateThread(serial->mthread, 0);
|
||||||
|
WaitForSingleObject(serial->mthread, INFINITE);
|
||||||
|
CloseHandle(serial->mthread);
|
||||||
|
}
|
||||||
WaitForSingleObject(serial->thread, INFINITE);
|
WaitForSingleObject(serial->thread, INFINITE);
|
||||||
|
|
||||||
serial_tty_free(serial->tty);
|
serial_tty_free(serial->tty);
|
||||||
@ -377,6 +434,7 @@ static void serial_free(DEVICE* device)
|
|||||||
Queue_Free(serial->queue);
|
Queue_Free(serial->queue);
|
||||||
list_free(serial->pending_irps);
|
list_free(serial->pending_irps);
|
||||||
CloseHandle(serial->stopEvent);
|
CloseHandle(serial->stopEvent);
|
||||||
|
CloseHandle(serial->newEvent);
|
||||||
CloseHandle(serial->thread);
|
CloseHandle(serial->thread);
|
||||||
free(serial);
|
free(serial);
|
||||||
}
|
}
|
||||||
@ -673,6 +731,13 @@ static BOOL serial_check_fds(SERIAL_DEVICE* serial)
|
|||||||
if (list_size(serial->pending_irps) == 0)
|
if (list_size(serial->pending_irps) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
FD_ZERO(&serial->read_fds);
|
||||||
|
FD_ZERO(&serial->write_fds);
|
||||||
|
|
||||||
|
serial->tv.tv_sec = 0;
|
||||||
|
serial->tv.tv_usec = 0;
|
||||||
|
serial->select_timeout = 0;
|
||||||
|
|
||||||
serial_set_fds(serial);
|
serial_set_fds(serial);
|
||||||
DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec);
|
DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec);
|
||||||
|
|
||||||
@ -739,11 +804,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||||||
serial->pending_irps = list_new();
|
serial->pending_irps = list_new();
|
||||||
|
|
||||||
serial->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
serial->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
serial->newEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial);
|
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial);
|
||||||
|
|
||||||
serial->thread = CreateThread(NULL, 0,
|
serial->thread = CreateThread(NULL, 0,
|
||||||
(LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL);
|
(LPTHREAD_START_ROUTINE) serial_thread_func, (void*) serial, 0, NULL);
|
||||||
|
serial->mthread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -128,7 +128,7 @@ static void* smartcard_thread_func(void* arg)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
DWORD status = WaitForSingleObject(2, ev, FALSE, INFINITE);
|
DWORD status = WaitForMultipleObjects(2, ev, FALSE, INFINITE);
|
||||||
|
|
||||||
if (status == WAIT_OBJECT_0 + 1)
|
if (status == WAIT_OBJECT_0 + 1)
|
||||||
break;
|
break;
|
||||||
|
@ -18,6 +18,15 @@
|
|||||||
set(MODULE_NAME "winpr-synch")
|
set(MODULE_NAME "winpr-synch")
|
||||||
set(MODULE_PREFIX "WINPR_SYNCH")
|
set(MODULE_PREFIX "WINPR_SYNCH")
|
||||||
|
|
||||||
|
INCLUDE (CheckLibraryExists)
|
||||||
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||||
|
check_library_exists(pthread pthread_tryjoin_np "" HAVE_PTHREAD_GNU_EXT)
|
||||||
|
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||||
|
|
||||||
|
if(HAVE_PTHREAD_GNU_EXT)
|
||||||
|
add_definitions(-D_GNU_SOURCE -DHAVE_PTHREAD_GNU_EXT)
|
||||||
|
endif(HAVE_PTHREAD_GNU_EXT)
|
||||||
|
|
||||||
include_directories(../thread)
|
include_directories(../thread)
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_SRCS
|
set(${MODULE_PREFIX}_SRCS
|
||||||
|
@ -77,7 +77,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
{
|
{
|
||||||
if (dwMilliseconds != INFINITE)
|
if (dwMilliseconds != INFINITE)
|
||||||
{
|
{
|
||||||
#if _GNU_SOURCE
|
#if HAVE_PTHREAD_GNU_EXT
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &timeout);
|
clock_gettime(CLOCK_REALTIME, &timeout);
|
||||||
@ -105,6 +105,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
|
|
||||||
mutex = (WINPR_MUTEX*) Object;
|
mutex = (WINPR_MUTEX*) Object;
|
||||||
|
|
||||||
|
#if HAVE_PTHREAD_GNU_EXT
|
||||||
if (dwMilliseconds != INFINITE)
|
if (dwMilliseconds != INFINITE)
|
||||||
{
|
{
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
@ -115,6 +116,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||||||
pthread_mutex_timedlock(&mutex->mutex, &timeout);
|
pthread_mutex_timedlock(&mutex->mutex, &timeout);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
pthread_mutex_lock(&mutex->mutex);
|
pthread_mutex_lock(&mutex->mutex);
|
||||||
}
|
}
|
||||||
else if (Type == HANDLE_TYPE_EVENT)
|
else if (Type == HANDLE_TYPE_EVENT)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user