winpr: cleanup polling code
Externalize all the polling logic in a pollset component. This patch prepares the support of APC and alertable state.
This commit is contained in:
Родитель
7d4a84ca89
Коммит
dfbbf3b618
|
@ -174,6 +174,7 @@ extern "C"
|
|||
|
||||
#define WAIT_OBJECT_0 0x00000000L
|
||||
#define WAIT_ABANDONED 0x00000080L
|
||||
#define WAIT_IO_COMPLETION 0x000000C0L
|
||||
|
||||
#ifndef WAIT_TIMEOUT
|
||||
#define WAIT_TIMEOUT 0x00000102L
|
||||
|
@ -202,7 +203,8 @@ extern "C"
|
|||
ULONG Version;
|
||||
DWORD Flags;
|
||||
|
||||
union {
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
HMODULE LocalizedReasonModule;
|
||||
|
|
|
@ -22,6 +22,8 @@ winpr_module_add(
|
|||
event.c
|
||||
init.c
|
||||
mutex.c
|
||||
pollset.c
|
||||
pollset.h
|
||||
semaphore.c
|
||||
sleep.c
|
||||
synch.h
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "pollset.h"
|
||||
#include <winpr/handle.h>
|
||||
#include "../log.h"
|
||||
|
||||
#define TAG WINPR_TAG("sync.pollset")
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
static DWORD handle_mode_to_pollevent(ULONG mode)
|
||||
{
|
||||
DWORD event = 0;
|
||||
|
||||
if (mode & WINPR_FD_READ)
|
||||
event |= POLLIN;
|
||||
|
||||
if (mode & WINPR_FD_WRITE)
|
||||
event |= POLLOUT;
|
||||
|
||||
return event;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL pollset_init(WINPR_POLL_SET* set, size_t nhandles)
|
||||
{
|
||||
#ifdef HAVE_POLL_H
|
||||
if (nhandles > MAXIMUM_WAIT_OBJECTS)
|
||||
{
|
||||
set->isStatic = FALSE;
|
||||
set->pollset = calloc(nhandles, sizeof(*set->pollset));
|
||||
if (!set->pollset)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
set->pollset = set->staticSet;
|
||||
set->isStatic = TRUE;
|
||||
}
|
||||
#else
|
||||
set->fdIndex = calloc(nhandles, sizeof(*set->fdIndex));
|
||||
if (!set->fdIndex)
|
||||
return FALSE;
|
||||
|
||||
FD_ZERO(&set->rset);
|
||||
FD_ZERO(&set->wset);
|
||||
set->maxFd = 0;
|
||||
set->nread = set->nwrite = 0;
|
||||
#endif
|
||||
|
||||
set->size = nhandles;
|
||||
set->fillIndex = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void pollset_uninit(WINPR_POLL_SET* set)
|
||||
{
|
||||
#ifdef HAVE_POLL_H
|
||||
if (!set->isStatic)
|
||||
free(set->pollset);
|
||||
#else
|
||||
free(set->fdIndex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pollset_reset(WINPR_POLL_SET* set)
|
||||
{
|
||||
#ifndef HAVE_POLL_H
|
||||
FD_ZERO(&set->rset);
|
||||
FD_ZERO(&set->wset);
|
||||
set->maxFd = 0;
|
||||
set->nread = set->nwrite = 0;
|
||||
#endif
|
||||
set->fillIndex = 0;
|
||||
}
|
||||
|
||||
BOOL pollset_add(WINPR_POLL_SET* set, int fd, ULONG mode)
|
||||
{
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd* item;
|
||||
if (set->fillIndex == set->size)
|
||||
return FALSE;
|
||||
|
||||
item = &set->pollset[set->fillIndex];
|
||||
item->fd = fd;
|
||||
item->revents = 0;
|
||||
item->events = handle_mode_to_pollevent(mode);
|
||||
#else
|
||||
FdIndex* fdIndex = &set->fdIndex[set->fillIndex];
|
||||
if (mode & WINPR_FD_READ)
|
||||
{
|
||||
FD_SET(fd, &set->rset);
|
||||
set->nread++;
|
||||
}
|
||||
|
||||
if (mode & WINPR_FD_WRITE)
|
||||
{
|
||||
FD_SET(fd, &set->wset);
|
||||
set->nwrite++;
|
||||
}
|
||||
|
||||
if (fd > set->maxFd)
|
||||
set->maxFd = fd;
|
||||
|
||||
fdIndex->fd = fd;
|
||||
fdIndex->mode = mode;
|
||||
#endif
|
||||
set->fillIndex++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int pollset_poll(WINPR_POLL_SET* set, DWORD dwMilliseconds)
|
||||
{
|
||||
int ret;
|
||||
#ifdef HAVE_POLL_H
|
||||
do
|
||||
{
|
||||
ret = poll(set->pollset, set->fillIndex, dwMilliseconds);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
#else
|
||||
struct timeval staticTimeout;
|
||||
struct timeval* timeout;
|
||||
|
||||
if (dwMilliseconds == INFINITE || dwMilliseconds == 0)
|
||||
{
|
||||
timeout = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout = &staticTimeout;
|
||||
timeout->tv_sec = dwMilliseconds / 1000;
|
||||
timeout->tv_usec = (dwMilliseconds % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ret = select(set->maxFd + 1, set->nread ? &set->rset : NULL,
|
||||
set->nwrite ? &set->wset : NULL, NULL, timeout);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx)
|
||||
{
|
||||
if (idx > set->fillIndex)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: index=%d out of pollset(fillIndex=%d)", __FUNCTION__, idx,
|
||||
set->fillIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
return !!(set->pollset[idx].revents & set->pollset[idx].events);
|
||||
#else
|
||||
FdIndex* fdIndex = &set->fdIndex[idx];
|
||||
if (fdIndex->fd < 0)
|
||||
return FALSE;
|
||||
|
||||
if ((fdIndex->mode & WINPR_FD_READ) && FD_ISSET(fdIndex->fd, &set->rset))
|
||||
return TRUE;
|
||||
|
||||
if ((fdIndex->mode & WINPR_FD_WRITE) && FD_ISSET(fdIndex->fd, &set->wset))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* pollset
|
||||
*
|
||||
* Copyright 2021 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef WINPR_LIBWINPR_SYNCH_POLLSET_H_
|
||||
#define WINPR_LIBWINPR_SYNCH_POLLSET_H_
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
ULONG mode;
|
||||
} FdIndex;
|
||||
#endif
|
||||
|
||||
struct winpr_poll_set
|
||||
{
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd* pollset;
|
||||
struct pollfd staticSet[MAXIMUM_WAIT_OBJECTS];
|
||||
BOOL isStatic;
|
||||
#else
|
||||
FdIndex* fdIndex;
|
||||
fd_set rset;
|
||||
fd_set wset;
|
||||
int nread, nwrite;
|
||||
int maxFd;
|
||||
#endif
|
||||
size_t fillIndex;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct winpr_poll_set WINPR_POLL_SET;
|
||||
|
||||
BOOL pollset_init(WINPR_POLL_SET* set, size_t nhandles);
|
||||
void pollset_uninit(WINPR_POLL_SET* set);
|
||||
void pollset_reset(WINPR_POLL_SET* set);
|
||||
BOOL pollset_add(WINPR_POLL_SET* set, int fd, ULONG mode);
|
||||
int pollset_poll(WINPR_POLL_SET* set, DWORD dwMilliseconds);
|
||||
BOOL pollset_isSignaled(WINPR_POLL_SET* set, size_t idx);
|
||||
|
||||
#endif /* WINPR_LIBWINPR_SYNCH_POLLSET_H_ */
|
|
@ -87,7 +87,7 @@ int TestSynchWaitableTimerAPC(int argc, char* argv[])
|
|||
if (rc == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (rc == 0x000000C0L) /* WAIT_IO_COMPLETION */
|
||||
if (rc == WAIT_IO_COMPLETION)
|
||||
continue;
|
||||
|
||||
printf("Failed to wait for completion event (%" PRIu32 ")\n", GetLastError());
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <winpr/platform.h>
|
||||
|
||||
#include "synch.h"
|
||||
#include "pollset.h"
|
||||
#include "../thread/thread.h"
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/debug.h>
|
||||
|
@ -161,20 +162,6 @@ 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 & WINPR_FD_READ)
|
||||
event |= POLLIN;
|
||||
|
||||
if (mode & WINPR_FD_WRITE)
|
||||
event |= POLLOUT;
|
||||
|
||||
return event;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ts_add_ms(struct timespec* ts, DWORD dwMilliseconds)
|
||||
{
|
||||
|
@ -184,53 +171,6 @@ static void ts_add_ms(struct timespec* ts, DWORD dwMilliseconds)
|
|||
ts->tv_nsec = ts->tv_nsec % 1000000000L;
|
||||
}
|
||||
|
||||
static int waitOnFd(int fd, ULONG mode, DWORD dwMilliseconds)
|
||||
{
|
||||
int status;
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd pollfds;
|
||||
pollfds.fd = fd;
|
||||
pollfds.events = handle_mode_to_pollevent(mode);
|
||||
pollfds.revents = 0;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollfds, 1, dwMilliseconds);
|
||||
} while ((status < 0) && (errno == EINTR));
|
||||
|
||||
#else
|
||||
struct timeval timeout;
|
||||
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 & WINPR_FD_READ)
|
||||
prfds = &rfds;
|
||||
|
||||
if (mode & WINPR_FD_WRITE)
|
||||
pwfds = &wfds;
|
||||
|
||||
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
|
||||
{
|
||||
timeout.tv_sec = dwMilliseconds / 1000;
|
||||
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status =
|
||||
select(fd + 1, prfds, pwfds, pefds, (dwMilliseconds == INFINITE) ? NULL : &timeout);
|
||||
} while (status < 0 && (errno == EINTR));
|
||||
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
||||
{
|
||||
|
@ -246,8 +186,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
|
||||
if (Type == HANDLE_TYPE_PROCESS)
|
||||
{
|
||||
WINPR_PROCESS* process;
|
||||
process = (WINPR_PROCESS*)Object;
|
||||
WINPR_PROCESS* process = (WINPR_PROCESS*)Object;
|
||||
|
||||
if (process->pid != waitpid(process->pid, &(process->status), 0))
|
||||
{
|
||||
|
@ -259,7 +198,8 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
process->dwExitCode = (DWORD)process->status;
|
||||
return WAIT_OBJECT_0;
|
||||
}
|
||||
else if (Type == HANDLE_TYPE_MUTEX)
|
||||
|
||||
if (Type == HANDLE_TYPE_MUTEX)
|
||||
{
|
||||
WINPR_MUTEX* mutex;
|
||||
mutex = (WINPR_MUTEX*)Object;
|
||||
|
@ -285,6 +225,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
else
|
||||
{
|
||||
int status;
|
||||
WINPR_POLL_SET pollset;
|
||||
int fd = winpr_Handle_getFd(Object);
|
||||
|
||||
if (fd < 0)
|
||||
|
@ -294,7 +235,21 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
status = waitOnFd(fd, Object->Mode, dwMilliseconds);
|
||||
if (!pollset_init(&pollset, 1))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to initialize pollset");
|
||||
SetLastError(ERROR_INTERNAL_ERROR);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
if (!pollset_add(&pollset, fd, Object->Mode))
|
||||
{
|
||||
pollset_uninit(&pollset);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
status = pollset_poll(&pollset, dwMilliseconds);
|
||||
pollset_uninit(&pollset);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
|
@ -340,14 +295,8 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
ULONG Type;
|
||||
BOOL signal_handled = FALSE;
|
||||
WINPR_HANDLE* Object;
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd* pollfds;
|
||||
#else
|
||||
int maxfd;
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
struct timeval timeout;
|
||||
#endif
|
||||
WINPR_POLL_SET pollset;
|
||||
DWORD ret = WAIT_FAILED;
|
||||
|
||||
if (!nCount || (nCount > MAXIMUM_WAIT_OBJECTS))
|
||||
{
|
||||
|
@ -355,6 +304,12 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
if (!pollset_init(&pollset, nCount))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to initialize pollset for nCount=%" PRIu32 "", nCount);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
if (bWaitAll)
|
||||
{
|
||||
signalled_idx = alloca(nCount * sizeof(BOOL));
|
||||
|
@ -363,25 +318,13 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
memset(poll_map, 0, nCount * sizeof(DWORD));
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
pollfds = alloca(nCount * sizeof(struct pollfd));
|
||||
#endif
|
||||
signalled = 0;
|
||||
|
||||
if (bWaitAll && (dwMilliseconds != INFINITE))
|
||||
clock_gettime(CLOCK_MONOTONIC, &starttime);
|
||||
|
||||
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);
|
||||
|
||||
polled = 0;
|
||||
|
||||
for (index = 0; index < nCount; index++)
|
||||
|
@ -398,66 +341,28 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
{
|
||||
WLog_ERR(TAG, "invalid event file descriptor");
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return WAIT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = winpr_Handle_getFd(Object);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid file descriptor");
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return WAIT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
pollfds[polled].fd = fd;
|
||||
pollfds[polled].events = handle_mode_to_pollevent(Object->Mode);
|
||||
pollfds[polled].revents = 0;
|
||||
#else
|
||||
|
||||
if (Object->Mode & WINPR_FD_READ)
|
||||
if (!pollset_add(&pollset, fd, Object->Mode))
|
||||
{
|
||||
FD_SET(fd, &rfds);
|
||||
prfds = &rfds;
|
||||
WLog_ERR(TAG, "unable to register fd in pollset");
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (Object->Mode & WINPR_FD_WRITE)
|
||||
{
|
||||
FD_SET(fd, &wfds);
|
||||
pwfds = &wfds;
|
||||
}
|
||||
|
||||
if (fd > maxfd)
|
||||
maxfd = fd;
|
||||
|
||||
#endif
|
||||
polled++;
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(pollfds, polled, dwMilliseconds);
|
||||
} while (status < 0 && errno == EINTR);
|
||||
|
||||
#else
|
||||
|
||||
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
|
||||
{
|
||||
timeout.tv_sec = dwMilliseconds / 1000;
|
||||
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status =
|
||||
select(maxfd + 1, prfds, pwfds, 0, (dwMilliseconds == INFINITE) ? NULL : &timeout);
|
||||
} while (status < 0 && errno == EINTR);
|
||||
|
||||
#endif
|
||||
|
||||
status = pollset_poll(&pollset, dwMilliseconds);
|
||||
if (status < 0)
|
||||
{
|
||||
#ifdef HAVE_POLL_H
|
||||
|
@ -469,11 +374,14 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
#endif
|
||||
winpr_log_backtrace(TAG, WLOG_ERROR, 20);
|
||||
SetLastError(ERROR_INTERNAL_ERROR);
|
||||
return WAIT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
return WAIT_TIMEOUT;
|
||||
{
|
||||
ret = WAIT_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bWaitAll && (dwMilliseconds != INFINITE))
|
||||
{
|
||||
|
@ -481,9 +389,12 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
diff = ts_difftime(&timenow, &starttime);
|
||||
|
||||
if (diff / 1000 > dwMilliseconds)
|
||||
return WAIT_TIMEOUT;
|
||||
else
|
||||
dwMilliseconds -= (diff / 1000);
|
||||
{
|
||||
ret = WAIT_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dwMilliseconds -= (diff / 1000);
|
||||
}
|
||||
|
||||
signal_handled = FALSE;
|
||||
|
@ -498,40 +409,17 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
else
|
||||
idx = index;
|
||||
|
||||
if (!winpr_Handle_GetInfo(lpHandles[idx], &Type, &Object))
|
||||
{
|
||||
WLog_ERR(TAG, "invalid hHandle.");
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
fd = winpr_Handle_getFd(lpHandles[idx]);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid file descriptor");
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return WAIT_FAILED;
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
signal_set = pollfds[index].revents & pollfds[index].events;
|
||||
#else
|
||||
|
||||
if (Object->Mode & WINPR_FD_READ)
|
||||
signal_set = FD_ISSET(fd, &rfds) ? 1 : 0;
|
||||
|
||||
if (Object->Mode & WINPR_FD_WRITE)
|
||||
signal_set |= FD_ISSET(fd, &wfds) ? 1 : 0;
|
||||
|
||||
#endif
|
||||
signal_set = pollset_isSignaled(&pollset, index);
|
||||
|
||||
if (signal_set)
|
||||
{
|
||||
DWORD rc = winpr_Handle_cleanup(lpHandles[idx]);
|
||||
|
||||
if (rc != WAIT_OBJECT_0)
|
||||
return rc;
|
||||
{
|
||||
WLog_ERR(TAG, "error in cleanup function for handle at index=%d", idx);
|
||||
ret = rc;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bWaitAll)
|
||||
{
|
||||
|
@ -546,19 +434,30 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
|
|||
}
|
||||
|
||||
if (!bWaitAll)
|
||||
return (WAIT_OBJECT_0 + index);
|
||||
{
|
||||
ret = (WAIT_OBJECT_0 + index);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (signalled >= nCount)
|
||||
return (WAIT_OBJECT_0);
|
||||
{
|
||||
ret = WAIT_OBJECT_0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
signal_handled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
pollset_reset(&pollset);
|
||||
} while (bWaitAll || !signal_handled);
|
||||
|
||||
WLog_ERR(TAG, "failed (unknown error)");
|
||||
SetLastError(ERROR_INTERNAL_ERROR);
|
||||
return WAIT_FAILED;
|
||||
|
||||
out:
|
||||
pollset_uninit(&pollset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll,
|
||||
|
@ -577,9 +476,10 @@ DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWait
|
|||
DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds,
|
||||
BOOL bAlertable)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: Not implemented.", __FUNCTION__);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
return WAIT_FAILED;
|
||||
if (!SetEvent(hObjectToSignal))
|
||||
return WAIT_FAILED;
|
||||
|
||||
return WaitForSingleObjectEx(hObjectToWaitOn, dwMilliseconds, bAlertable);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче