Added write event support to handle functions.

Allows the WinPR HANDLE functions WaitForSingleObject and
WaitForMultipleObjects to signal in case of write events.
This is used by CreateFileDescriptor and SetEventFileDescriptor,
which got an API change accomodating for this new feature.
This commit is contained in:
Armin Novak 2015-07-03 09:25:41 +02:00
parent 7dc96c412f
commit 6243a9374b
6 changed files with 128 additions and 62 deletions

View File

@ -41,8 +41,12 @@ extern "C" {
WINPR_API BOOL CloseHandle(HANDLE hObject);
WINPR_API BOOL DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle,
LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions);
WINPR_API BOOL DuplicateHandle(HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
HANDLE hTargetProcessHandle,
LPHANDLE lpTargetHandle,
DWORD dwDesiredAccess,
BOOL bInheritHandle, DWORD dwOptions);
WINPR_API BOOL GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags);
WINPR_API BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags);

View File

@ -30,6 +30,7 @@
#include <winpr/wtypes.h>
#include <winpr/error.h>
#include <winpr/handle.h>
#include <winpr/winsock.h>
#include <winpr/nt.h>
@ -338,9 +339,9 @@ WINPR_API BOOL WINAPI DeleteSynchronizationBarrier(LPSYNCHRONIZATION_BARRIER lpB
WINPR_API VOID USleep(DWORD dwMicroseconds);
WINPR_API HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState, int FileDescriptor);
BOOL bManualReset, BOOL bInitialState, int FileDescriptor, ULONG mode);
WINPR_API HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState, int FileDescriptor);
BOOL bManualReset, BOOL bInitialState, int FileDescriptor, ULONG mode);
WINPR_API HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState, void* pObject);
@ -352,7 +353,7 @@ WINPR_API HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
#endif
WINPR_API int GetEventFileDescriptor(HANDLE hEvent);
WINPR_API int SetEventFileDescriptor(HANDLE hEvent, int FileDescriptor);
WINPR_API int SetEventFileDescriptor(HANDLE hEvent, int FileDescriptor, ULONG mode);
WINPR_API void* GetEventWaitObject(HANDLE hEvent);

View File

@ -48,7 +48,7 @@ BOOL CloseHandle(HANDLE hObject)
ULONG Type;
WINPR_HANDLE *Object;
if (!winpr_Handle_GetInfo(hObject, &Type, (PVOID*) &Object))
if (!winpr_Handle_GetInfo(hObject, &Type, &Object))
return FALSE;
if (!Object)

View File

@ -23,6 +23,7 @@
#include <winpr/handle.h>
#include <winpr/file.h>
#include <winpr/synch.h>
#include <winpr/winsock.h>
#define HANDLE_TYPE_NONE 0
#define HANDLE_TYPE_PROCESS 1
@ -41,6 +42,7 @@
#define WINPR_HANDLE_DEF() \
ULONG Type; \
ULONG Mode; \
HANDLE_OPS *ops
typedef BOOL (*pcIsHandled)(HANDLE handle);
@ -68,10 +70,16 @@ struct winpr_handle
};
typedef struct winpr_handle WINPR_HANDLE;
#define WINPR_HANDLE_SET_TYPE(_handle, _type) \
_handle->Type = _type
static INLINE void WINPR_HANDLE_SET_TYPE_AND_MODE(void* _handle,
ULONG _type, ULONG _mode)
{
WINPR_HANDLE* hdl = (WINPR_HANDLE*)_handle;
static INLINE BOOL winpr_Handle_GetInfo(HANDLE handle, ULONG* pType, PVOID* pObject)
hdl->Type = _type;
hdl->Mode = _mode;
}
static INLINE BOOL winpr_Handle_GetInfo(HANDLE handle, ULONG* pType, WINPR_HANDLE** pObject)
{
WINPR_HANDLE* wHandle;
@ -91,7 +99,7 @@ static INLINE int winpr_Handle_getFd(HANDLE handle)
WINPR_HANDLE *hdl;
ULONG type;
if (!winpr_Handle_GetInfo(handle, &type, (PVOID*)&hdl))
if (!winpr_Handle_GetInfo(handle, &type, &hdl))
return -1;
if (!hdl || !hdl->ops->GetFd)
@ -105,7 +113,7 @@ static INLINE DWORD winpr_Handle_cleanup(HANDLE handle)
WINPR_HANDLE *hdl;
ULONG type;
if (!winpr_Handle_GetInfo(handle, &type, (PVOID*)&hdl))
if (!winpr_Handle_GetInfo(handle, &type, &hdl))
return WAIT_FAILED;
if (!hdl)

View File

@ -78,23 +78,22 @@ BOOL EventCloseHandle(HANDLE handle) {
if (!EventIsHandled(handle))
return FALSE;
if (!event->bAttached)
{
if (event->pipe_fd[0] != -1)
{
close(event->pipe_fd[0]);
event->pipe_fd[0] = -1;
}
if (!event->bAttached)
{
if (event->pipe_fd[0] != -1)
{
close(event->pipe_fd[0]);
event->pipe_fd[0] = -1;
}
if (event->pipe_fd[1] != -1)
{
close(event->pipe_fd[1]);
event->pipe_fd[1] = -1;
}
}
if (event->pipe_fd[1] != -1)
{
close(event->pipe_fd[1]);
event->pipe_fd[1] = -1;
}
}
free(event);
return TRUE;
free(event);
return TRUE;
}
static HANDLE_OPS ops = {
@ -114,7 +113,7 @@ HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
event->bAttached = FALSE;
event->bManualReset = bManualReset;
event->ops = &ops;
WINPR_HANDLE_SET_TYPE(event, HANDLE_TYPE_EVENT);
WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, FD_READ);
if (!event->bManualReset)
{
@ -200,7 +199,7 @@ static int eventfd_write(int fd, eventfd_t value)
BOOL SetEvent(HANDLE hEvent)
{
ULONG Type;
PVOID Object;
WINPR_HANDLE* Object;
int length;
BOOL status;
WINPR_EVENT* event;
@ -241,7 +240,7 @@ BOOL SetEvent(HANDLE hEvent)
BOOL ResetEvent(HANDLE hEvent)
{
ULONG Type;
PVOID Object;
WINPR_HANDLE* Object;
int length;
BOOL status = TRUE;
WINPR_EVENT* event;
@ -274,7 +273,9 @@ BOOL ResetEvent(HANDLE hEvent)
#endif
HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, int FileDescriptor)
HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState,
int FileDescriptor, ULONG mode)
{
#ifndef _WIN32
WINPR_EVENT* event;
@ -288,7 +289,7 @@ HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL
event->pipe_fd[0] = FileDescriptor;
event->pipe_fd[1] = -1;
event->ops = &ops;
WINPR_HANDLE_SET_TYPE(event, HANDLE_TYPE_EVENT);
WINPR_HANDLE_SET_TYPE_AND_MODE(event, HANDLE_TYPE_EVENT, mode);
handle = (HANDLE) event;
}
@ -298,9 +299,12 @@ HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL
#endif
}
HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, int FileDescriptor)
HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState,
int FileDescriptor, ULONG mode)
{
return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState, FileDescriptor);
return CreateFileDescriptorEventW(lpEventAttributes, bManualReset,
bInitialState, FileDescriptor, mode);
}
/**
@ -310,7 +314,8 @@ HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState, void* pObject)
{
#ifndef _WIN32
return CreateFileDescriptorEventW(lpEventAttributes, bManualReset, bInitialState, (int)(ULONG_PTR) pObject);
return CreateFileDescriptorEventW(lpEventAttributes, bManualReset,
bInitialState, (int)(ULONG_PTR) pObject, FD_READ);
#else
HANDLE hEvent = NULL;
DuplicateHandle(GetCurrentProcess(), pObject, GetCurrentProcess(), &hEvent, 0, FALSE, DUPLICATE_SAME_ACCESS);
@ -327,7 +332,7 @@ int GetEventFileDescriptor(HANDLE hEvent)
{
#ifndef _WIN32
ULONG Type;
PVOID Object;
WINPR_HANDLE* Object;
WINPR_EVENT* event;
if (!winpr_Handle_GetInfo(hEvent, &Type, &Object))
@ -360,17 +365,19 @@ int GetEventFileDescriptor(HANDLE hEvent)
* This file descriptor is not usable on Windows
*/
int SetEventFileDescriptor(HANDLE hEvent, int FileDescriptor)
int SetEventFileDescriptor(HANDLE hEvent, int FileDescriptor, ULONG mode)
{
#ifndef _WIN32
ULONG Type;
PVOID Object;
WINPR_HANDLE* Object;
WINPR_EVENT* event;
if (!winpr_Handle_GetInfo(hEvent, &Type, &Object))
return -1;
event = (WINPR_EVENT*) Object;
event->bAttached = TRUE;
event->Mode = mode;
event->pipe_fd[0] = FileDescriptor;
return 0;
#else

View File

@ -44,6 +44,7 @@
#include "synch.h"
#include "../thread/thread.h"
#include <winpr/thread.h>
#include <winpr/debug.h>
#include "../log.h"
#define TAG WINPR_TAG("sync.wait")
@ -132,6 +133,19 @@ static int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec
}
#endif
#ifdef HAVE_POLL_H
static DWORD handle_mode_to_pollevent(ULONG mode)
{
DWORD event = 0;
if (mode & FD_READ)
event |= POLLIN;
if (mode & FD_WRITE)
event |= POLLOUT;
return event;
}
#endif
static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds)
{
ts->tv_sec += dwMilliseconds / 1000L;
@ -140,13 +154,13 @@ static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds)
ts->tv_nsec = ts->tv_nsec % 1000000000L;
}
static int waitOnFd(int fd, DWORD dwMilliseconds)
static int waitOnFd(int fd, ULONG mode, DWORD dwMilliseconds)
{
int status;
#ifdef HAVE_POLL_H
struct pollfd pollfds;
pollfds.fd = fd;
pollfds.events = POLLIN;
pollfds.events = handle_mode_to_pollevent(mode);
pollfds.revents = 0;
do
@ -157,11 +171,21 @@ static int waitOnFd(int fd, DWORD dwMilliseconds)
#else
struct timeval timeout;
fd_set rfds;
fd_set rfds, wfds;
fd_set* prfds = NULL;
fd_set* pwfds = NULL;
fd_set* pefds = NULL;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
ZeroMemory(&timeout, sizeof(timeout));
if (mode & FD_READ)
prfds = &rfds;
if (mode & FD_WRITE)
pwfds = &wfds;
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_sec = dwMilliseconds / 1000;
@ -170,7 +194,7 @@ static int waitOnFd(int fd, DWORD dwMilliseconds)
do
{
status = select(fd + 1, &rfds, NULL, NULL, (dwMilliseconds == INFINITE) ? NULL : &timeout);
status = select(fd + 1, prfds, pwfds, pefds, (dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && (errno == EINTR));
@ -181,7 +205,7 @@ static int waitOnFd(int fd, DWORD dwMilliseconds)
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
ULONG Type;
PVOID Object;
WINPR_HANDLE* Object;
if (!winpr_Handle_GetInfo(hHandle, &Type, &Object))
{
@ -193,8 +217,10 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{
WINPR_PROCESS *process;
process = (WINPR_PROCESS *) Object;
int rc;
if (waitpid(process->pid, &(process->status), 0) != -1)
rc = waitpid(process->pid, &(process->status), 0);
if (rc != process->pid)
{
WLog_ERR(TAG, "waitpid failure [%d] %s", errno, strerror(errno));
return WAIT_FAILED;
@ -233,7 +259,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
if (fd < 0)
return WAIT_FAILED;
status = waitOnFd(fd, dwMilliseconds);
status = waitOnFd(fd, Object->Mode, dwMilliseconds);
if (status < 0)
{
@ -270,12 +296,14 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
int index;
int status;
ULONG Type;
PVOID Object;
BOOL signal_handled = FALSE;
WINPR_HANDLE* Object;
#ifdef HAVE_POLL_H
struct pollfd *pollfds;
#else
int maxfd;
fd_set fds;
fd_set rfds;
fd_set wfds;
struct timeval timeout;
#endif
@ -300,14 +328,18 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
do
{
#ifndef HAVE_POLL_H
fd_set* prfds = NULL;
fd_set* pwfds = NULL;
maxfd = 0;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
ZeroMemory(&timeout, sizeof(timeout));
#endif
if (bWaitAll && (dwMilliseconds != INFINITE))
clock_gettime(CLOCK_MONOTONIC, &starttime);
#ifndef HAVE_POLL_H
maxfd = 0;
FD_ZERO(&fds);
ZeroMemory(&timeout, sizeof(timeout));
#endif
polled = 0;
for (index = 0; index < nCount; index++)
@ -336,10 +368,16 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
#ifdef HAVE_POLL_H
pollfds[polled].fd = fd;
pollfds[polled].events = POLLIN;
pollfds[polled].events = handle_mode_to_pollevent(Object->Mode);
pollfds[polled].revents = 0;
#else
FD_SET(fd, &fds);
FD_SET(fd, &rfds);
FD_SET(fd, &wfds);
if (Object->Mode & FD_READ)
prfds = &rfds;
if (Object->Mode & FD_WRITE)
pwfds = &wfds;
if (fd > maxfd)
maxfd = fd;
@ -366,8 +404,8 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
do
{
status = select(maxfd + 1, &fds, 0, 0,
(dwMilliseconds == INFINITE) ? NULL : &timeout);
status = select(maxfd + 1, prfds, pwfds, 0,
(dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && errno == EINTR);
@ -376,12 +414,13 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
if (status < 0)
{
#ifdef HAVE_POLL_H
WLog_ERR(TAG, "poll() failure [%d] %s", errno,
WLog_ERR(TAG, "poll() handle %d (%d) failure [%d] %s", index, nCount, errno,
strerror(errno));
#else
WLog_ERR(TAG, "select() failure [%d] %s", errno,
WLog_ERR(TAG, "select() handle %d (%d) failure [%d] %s", index, nCount, errno,
strerror(errno));
#endif
winpr_log_backtrace(TAG, WLOG_ERROR, 20);
return WAIT_FAILED;
}
@ -399,9 +438,11 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
dwMilliseconds -= (diff / 1000);
}
signal_handled = FALSE;
for (index = 0; index < polled; index++)
{
DWORD idx;
BOOL signal_set = FALSE;
if (bWaitAll)
idx = poll_map[index];
@ -423,11 +464,14 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
}
#ifdef HAVE_POLL_H
if (pollfds[index].revents & POLLIN)
signal_set = pollfds[index].revents & pollfds[index].events;
#else
if (FD_ISSET(fd, &fds))
if (Object->Mode & FD_READ)
signal_set = FD_ISSET(fd, &rfds);
if (Object->Mode & FD_WRITE)
signal_set = FD_ISSET(fd, &wfds);
#endif
if (signal_set)
{
DWORD rc = winpr_Handle_cleanup(lpHandles[idx]);
if (rc != WAIT_OBJECT_0)
@ -450,10 +494,12 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
if (bWaitAll && (signalled >= nCount))
return (WAIT_OBJECT_0);
signal_handled = TRUE;
}
}
}
while (bWaitAll);
while (bWaitAll || !signal_handled);
WLog_ERR(TAG, "failed (unknown error)");
return WAIT_FAILED;