Use poll() instead of select() when available

select() has the major drawback that it cannot handle file descriptor
that are bigger than 1024. This patch makes use of poll() instead of
select() when poll() support is available.
This commit is contained in:
Hardening 2014-07-02 15:15:46 +02:00
parent b86c3b038b
commit 542811291c
9 changed files with 296 additions and 144 deletions

View File

@ -369,6 +369,7 @@ if(UNIX OR CYGWIN)
check_include_files(sys/eventfd.h HAVE_AIO_H) check_include_files(sys/eventfd.h HAVE_AIO_H)
check_include_files(sys/eventfd.h HAVE_EVENTFD_H) check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
check_include_files(sys/timerfd.h HAVE_TIMERFD_H) check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
check_include_files(poll.h HAVE_POLL_H)
set(X11_FEATURE_TYPE "RECOMMENDED") set(X11_FEATURE_TYPE "RECOMMENDED")
else() else()
set(X11_FEATURE_TYPE "DISABLED") set(X11_FEATURE_TYPE "DISABLED")

View File

@ -24,6 +24,7 @@
#cmakedefine HAVE_TIMERFD_H #cmakedefine HAVE_TIMERFD_H
#cmakedefine HAVE_TM_GMTOFF #cmakedefine HAVE_TM_GMTOFF
#cmakedefine HAVE_AIO_H #cmakedefine HAVE_AIO_H
#cmakedefine HAVE_POLL_H
#cmakedefine HAVE_PTHREAD_GNU_EXT #cmakedefine HAVE_PTHREAD_GNU_EXT
#cmakedefine HAVE_VALGRIND_MEMCHECK_H #cmakedefine HAVE_VALGRIND_MEMCHECK_H

View File

@ -41,6 +41,13 @@
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <net/if.h> #include <net/if.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
#include <time.h>
#include <sys/select.h>
#endif
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#ifndef SOL_TCP #ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP #define SOL_TCP IPPROTO_TCP
@ -739,6 +746,83 @@ HANDLE tcp_get_event_handle(rdpTcp* tcp)
#endif #endif
} }
int tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds)
{
int status;
#ifdef HAVE_POLL_H
struct pollfd pollset;
pollset.fd = tcp->sockfd;
pollset.events = POLLIN;
pollset.revents = 0;
do
{
status = poll(&pollset, 1, dwMilliSeconds);
}
while ((status < 0) && (errno == EINTR));
#else
struct timeval tv;
fd_set rset;
FD_ZERO(&rset);
FD_SET(tcp->sockfd, &rset);
if (dwMilliSeconds)
{
tv.tv_sec = dwMilliSeconds / 1000;
tv.tv_usec = (dwMilliSeconds % 1000) * 1000;
}
do
{
status = select(tcp->sockfd + 1, &rset, NULL, NULL, dwMilliSeconds ? &tv : NULL);
}
while ((status < 0) && (errno == EINTR));
#endif
return status;
}
int tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds)
{
int status;
#ifdef HAVE_POLL_H
struct pollfd pollset;
pollset.fd = tcp->sockfd;
pollset.events = POLLOUT;
pollset.revents = 0;
do
{
status = poll(&pollset, 1, dwMilliSeconds);
}
while ((status < 0) && (errno == EINTR));
#else
struct timeval tv;
fd_set rset;
FD_ZERO(&rset);
FD_SET(tcp->sockfd, &rset);
if (dwMilliSeconds)
{
tv.tv_sec = dwMilliSeconds / 1000;
tv.tv_usec = (dwMilliSeconds % 1000) * 1000;
}
do
{
status = select(tcp->sockfd + 1, NULL, &rset, NULL, dwMilliSeconds ? &tv : NULL);
}
while ((status < 0) && (errno == EINTR));
#endif
return status;
}
rdpTcp* tcp_new(rdpSettings* settings) rdpTcp* tcp_new(rdpSettings* settings)
{ {
rdpTcp* tcp; rdpTcp* tcp;

View File

@ -64,8 +64,8 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout);
BOOL tcp_disconnect(rdpTcp* tcp); BOOL tcp_disconnect(rdpTcp* tcp);
int tcp_read(rdpTcp* tcp, BYTE* data, int length); int tcp_read(rdpTcp* tcp, BYTE* data, int length);
int tcp_write(rdpTcp* tcp, BYTE* data, int length); int tcp_write(rdpTcp* tcp, BYTE* data, int length);
int tcp_wait_read(rdpTcp* tcp); int tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds);
int tcp_wait_write(rdpTcp* tcp); int tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds);
BOOL tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking); BOOL tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking);
BOOL tcp_set_keep_alive_mode(rdpTcp* tcp); BOOL tcp_set_keep_alive_mode(rdpTcp* tcp);
int tcp_attach(rdpTcp* tcp, int sockfd); int tcp_attach(rdpTcp* tcp, int sockfd);

View File

@ -43,9 +43,7 @@
#ifndef _WIN32 #ifndef _WIN32
#include <netdb.h> #include <netdb.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/select.h> #endif /* _WIN32 */
#include <sys/time.h>
#endif
#ifdef HAVE_VALGRIND_MEMCHECK_H #ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
@ -642,69 +640,37 @@ UINT32 nla_header_length(wStream* s)
static int transport_wait_for_read(rdpTransport* transport) static int transport_wait_for_read(rdpTransport* transport)
{ {
struct timeval tv; rdpTcp *tcpIn = transport->TcpIn;
fd_set rset, wset;
fd_set *rsetPtr = NULL, *wsetPtr = NULL;
rdpTcp *tcpIn;
tcpIn = transport->TcpIn;
if (tcpIn->readBlocked) if (tcpIn->readBlocked)
{ {
rsetPtr = &rset; return tcp_wait_read(tcpIn, 1000);
FD_ZERO(rsetPtr);
FD_SET(tcpIn->sockfd, rsetPtr);
} }
else if (tcpIn->writeBlocked) else if (tcpIn->writeBlocked)
{ {
wsetPtr = &wset; return tcp_wait_write(tcpIn, 1000);
FD_ZERO(wsetPtr);
FD_SET(tcpIn->sockfd, wsetPtr);
} }
if (!wsetPtr && !rsetPtr) USleep(1000);
{ return 0;
USleep(1000);
return 0;
}
tv.tv_sec = 0;
tv.tv_usec = 1000;
return select(tcpIn->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
} }
static int transport_wait_for_write(rdpTransport* transport) static int transport_wait_for_write(rdpTransport* transport)
{ {
struct timeval tv;
fd_set rset, wset;
fd_set *rsetPtr = NULL, *wsetPtr = NULL;
rdpTcp *tcpOut; rdpTcp *tcpOut;
tcpOut = transport->SplitInputOutput ? transport->TcpOut : transport->TcpIn; tcpOut = transport->SplitInputOutput ? transport->TcpOut : transport->TcpIn;
if (tcpOut->writeBlocked) if (tcpOut->writeBlocked)
{ {
wsetPtr = &wset; return tcp_wait_write(tcpOut, 1000);
FD_ZERO(wsetPtr);
FD_SET(tcpOut->sockfd, wsetPtr);
} }
else if (tcpOut->readBlocked) else if (tcpOut->readBlocked)
{ {
rsetPtr = &rset; return tcp_wait_read(tcpOut, 1000);
FD_ZERO(rsetPtr);
FD_SET(tcpOut->sockfd, rsetPtr);
} }
if (!wsetPtr && !rsetPtr) USleep(1000);
{ return 0;
USleep(1000);
return 0;
}
tv.tv_sec = 0;
tv.tv_usec = 1000;
return select(tcpOut->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
} }
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes) int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)

View File

@ -33,6 +33,11 @@
#include <freerdp/crypto/tls.h> #include <freerdp/crypto/tls.h>
#include "../core/tcp.h" #include "../core/tcp.h"
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
struct _BIO_RDP_TLS struct _BIO_RDP_TLS
{ {
SSL* ssl; SSL* ssl;
@ -586,8 +591,12 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
do do
{ {
#ifdef HAVE_POLL_H
struct pollfd pollfds;
#else
struct timeval tv; struct timeval tv;
fd_set rset; fd_set rset;
#endif
int fd; int fd;
status = BIO_do_handshake(tls->bio); status = BIO_do_handshake(tls->bio);
@ -600,8 +609,6 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
/* we select() only for read even if we should test both read and write /* we select() only for read even if we should test both read and write
* depending of what have blocked */ * depending of what have blocked */
FD_ZERO(&rset);
fd = BIO_get_fd(tls->bio, NULL); fd = BIO_get_fd(tls->bio, NULL);
if (fd < 0) if (fd < 0)
@ -610,12 +617,24 @@ int tls_do_handshake(rdpTls* tls, BOOL clientMode)
return -1; return -1;
} }
#ifdef HAVE_POLL_H
pollfds.fd = fd;
pollfds.events = POLLIN;
pollfds.revents = 0;
do
{
status = poll(&pollfds, 1, 10 * 1000);
}
while ((status < 0) && (errno == EINTR));
#else
FD_ZERO(&rset);
FD_SET(fd, &rset); FD_SET(fd, &rset);
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 10 * 1000; /* 10ms */ tv.tv_usec = 10 * 1000; /* 10ms */
status = select(fd + 1, &rset, NULL, NULL, &tv); status = _select(fd + 1, &rset, NULL, NULL, &tv);
#endif
if (status < 0) if (status < 0)
{ {
fprintf(stderr, "%s: error during select()\n", __FUNCTION__); fprintf(stderr, "%s: error during select()\n", __FUNCTION__);
@ -830,9 +849,13 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
{ {
int status, nchunks, commitedBytes; int status, nchunks, commitedBytes;
rdpTcp *tcp; rdpTcp *tcp;
#ifdef HAVE_POLL_H
struct pollfd pollfds;
#else
fd_set rset, wset; fd_set rset, wset;
fd_set *rsetPtr, *wsetPtr; fd_set *rsetPtr, *wsetPtr;
struct timeval tv; struct timeval tv;
#endif
BIO* bio = tls->bio; BIO* bio = tls->bio;
DataChunk chunks[2]; DataChunk chunks[2];
@ -855,9 +878,34 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
if (!BIO_should_retry(bio)) if (!BIO_should_retry(bio))
return -1; return -1;
#ifdef HAVE_POLL_H
pollfds.fd = tcp->sockfd;
pollfds.revents = 0;
pollfds.events = 0;
if (tcp->writeBlocked)
{
pollfds.events |= POLLOUT;
}
else if (tcp->readBlocked)
{
pollfds.events |= POLLIN;
}
else
{
fprintf(stderr, "%s: weird we're blocked but the underlying is not read or write blocked !\n", __FUNCTION__);
USleep(10);
continue;
}
do
{
status = poll(&pollfds, 1, 100);
}
while ((status < 0) && (errno == EINTR));
#else
/* we try to handle SSL want_read and want_write nicely */ /* we try to handle SSL want_read and want_write nicely */
rsetPtr = wsetPtr = 0; rsetPtr = wsetPtr = NULL;
if (tcp->writeBlocked) if (tcp->writeBlocked)
{ {
@ -881,8 +929,8 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 100 * 1000; tv.tv_usec = 100 * 1000;
status = select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv); status = _select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
#endif
if (status < 0) if (status < 0)
return -1; return -1;
} }
@ -911,13 +959,24 @@ int tls_write_all(rdpTls* tls, const BYTE* data, int length)
if (!BIO_should_retry(tcp->socketBio)) if (!BIO_should_retry(tcp->socketBio))
goto out_fail; goto out_fail;
#ifdef HAVE_POLL_H
pollfds.fd = tcp->sockfd;
pollfds.events = POLLIN;
pollfds.revents = 0;
do
{
status = poll(&pollfds, 1, 100);
}
while ((status < 0) && (errno == EINTR));
#else
FD_ZERO(&rset); FD_ZERO(&rset);
FD_SET(tcp->sockfd, &rset); FD_SET(tcp->sockfd, &rset);
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 100 * 1000; tv.tv_usec = 100 * 1000;
status = select(tcp->sockfd + 1, &rset, NULL, NULL, &tv); status = _select(tcp->sockfd + 1, &rset, NULL, NULL, &tv);
#endif
if (status < 0) if (status < 0)
goto out_fail; goto out_fail;
} }

View File

@ -41,11 +41,16 @@
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <net/if.h> #include <net/if.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
#include <sys/select.h>
#endif
#ifdef __APPLE__ #ifdef __APPLE__
#ifndef TCP_KEEPIDLE #ifndef TCP_KEEPIDLE
#define TCP_KEEPIDLE TCP_KEEPALIVE #define TCP_KEEPIDLE TCP_KEEPALIVE
@ -186,8 +191,14 @@ int freerdp_tcp_write(int sockfd, BYTE* data, int length)
int freerdp_tcp_wait_read(int sockfd) int freerdp_tcp_wait_read(int sockfd)
{ {
int status;
#ifdef HAVE_POLL_H
struct pollfd pollfds;
#else
fd_set fds; fd_set fds;
struct timeval timeout; struct timeval timeout;
#endif
if (sockfd < 1) if (sockfd < 1)
{ {
@ -195,37 +206,61 @@ int freerdp_tcp_wait_read(int sockfd)
return 0 ; return 0 ;
} }
#ifdef HAVE_POLL_H
pollfds.fd = sockfd;
pollfds.events = POLLIN;
pollfds.revents = 0;
do
{
status = poll(&pollfds, 1, 5 * 1000);
}
while ((status < 0) && (errno == EINTR));
#else
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(sockfd, &fds); FD_SET(sockfd, &fds);
timeout.tv_sec = 5; timeout.tv_sec = 5;
timeout.tv_usec = 0; timeout.tv_usec = 0;
select(sockfd+1, &fds, NULL, NULL, &timeout); status = _select(sockfd+1, &fds, NULL, NULL, &timeout);
if (!FD_ISSET(sockfd, &fds)) #endif
return -1;
return 0; return status > 0 ? 1 : 0;
} }
int freerdp_tcp_wait_write(int sockfd) int freerdp_tcp_wait_write(int sockfd)
{ {
int status;
#ifdef HAVE_POLL_H
struct pollfd pollfds;
#else
fd_set fds; fd_set fds;
struct timeval timeout; struct timeval timeout;
#endif
if (sockfd < 1) if (sockfd < 1)
{ {
fprintf(stderr, "Invalid socket to watch: %d\n", sockfd); fprintf(stderr, "Invalid socket to watch: %d\n", sockfd);
return 0; return 0 ;
} }
#ifdef HAVE_POLL_H
pollfds.fd = sockfd;
pollfds.events = POLLOUT;
pollfds.revents = 0;
do
{
status = poll(&pollfds, 1, 5 * 1000);
}
while ((status < 0) && (errno == EINTR));
#else
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(sockfd, &fds); FD_SET(sockfd, &fds);
timeout.tv_sec = 5; timeout.tv_sec = 5;
timeout.tv_usec = 0; timeout.tv_usec = 0;
select(sockfd+1, NULL, &fds, NULL, &timeout); status = _select(sockfd+1, NULL, &fds, NULL, &timeout);
if (!FD_ISSET(sockfd, &fds)) #endif
return -1;
return 0; return status > 0 ? 1 : 0;
} }
int freerdp_tcp_disconnect(int sockfd) int freerdp_tcp_disconnect(int sockfd)

View File

@ -3,6 +3,7 @@
* Synchronization Functions * Synchronization Functions
* *
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 Hardening <contact@hardening-consulting.com>
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +26,10 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
@ -164,6 +169,47 @@ static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds)
ts->tv_nsec = ts->tv_nsec % 1000000000L; ts->tv_nsec = ts->tv_nsec % 1000000000L;
} }
static int waitOnFd(int fd, DWORD dwMilliseconds)
{
int status;
#ifdef HAVE_POLL_H
struct pollfd pollfds;
pollfds.fd = fd;
pollfds.events = POLLIN;
pollfds.revents = 0;
do
{
status = poll(&pollfds, 1, dwMilliseconds);
}
while ((status < 0) && (errno == EINTR));
#else
struct timespec timeout;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
ZeroMemory(&timeout, sizeof(timeout));
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_sec = dwMilliseconds / 1000;
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
}
do
{
status = select(fd + 1, &rfds, NULL, NULL, (dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && (errno == EINTR));
#endif
return status;
}
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{ {
ULONG Type; ULONG Type;
@ -256,29 +302,11 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
else if (Type == HANDLE_TYPE_EVENT) else if (Type == HANDLE_TYPE_EVENT)
{ {
int status; int status;
fd_set rfds;
WINPR_EVENT* event; WINPR_EVENT* event;
struct timeval timeout;
event = (WINPR_EVENT*) Object; event = (WINPR_EVENT*) Object;
FD_ZERO(&rfds); status = waitOnFd(event->pipe_fd[0], dwMilliseconds);
FD_SET(event->pipe_fd[0], &rfds);
ZeroMemory(&timeout, sizeof(timeout));
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_sec = dwMilliseconds / 1000;
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
}
do
{
status = select(event->pipe_fd[0] + 1, &rfds, NULL, NULL,
(dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && (errno == EINTR));
if (status < 0) if (status < 0)
{ {
fprintf(stderr, "WaitForSingleObject: event select() failure [%d] %s\n", errno, strerror(errno)); fprintf(stderr, "WaitForSingleObject: event select() failure [%d] %s\n", errno, strerror(errno));
@ -299,26 +327,8 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{ {
int status; int status;
int length; int length;
fd_set rfds;
struct timeval timeout;
FD_ZERO(&rfds);
FD_SET(semaphore->pipe_fd[0], &rfds);
ZeroMemory(&timeout, sizeof(timeout));
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_sec = dwMilliseconds / 1000;
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
}
do
{
status = select(semaphore->pipe_fd[0] + 1, &rfds, 0, 0,
(dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && (errno == EINTR));
status = waitOnFd(semaphore->pipe_fd[0], dwMilliseconds);
if (status < 0) if (status < 0)
{ {
fprintf(stderr, "WaitForSingleObject: semaphore select() failure [%d] %s\n", errno, strerror(errno)); fprintf(stderr, "WaitForSingleObject: semaphore select() failure [%d] %s\n", errno, strerror(errno));
@ -356,27 +366,9 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
if (timer->fd != -1) if (timer->fd != -1)
{ {
int status; int status;
fd_set rfds;
UINT64 expirations; UINT64 expirations;
struct timeval timeout;
FD_ZERO(&rfds);
FD_SET(timer->fd, &rfds);
ZeroMemory(&timeout, sizeof(timeout));
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_sec = dwMilliseconds / 1000;
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
}
do
{
status = select(timer->fd + 1, &rfds, 0, 0,
(dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && (errno == EINTR));
status = waitOnFd(timer->fd, dwMilliseconds);
if (status < 0) if (status < 0)
{ {
fprintf(stderr, "WaitForSingleObject: timer select() failure [%d] %s\n", errno, strerror(errno)); fprintf(stderr, "WaitForSingleObject: timer select() failure [%d] %s\n", errno, strerror(errno));
@ -420,8 +412,6 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
{ {
int fd; int fd;
int status; int status;
fd_set rfds;
struct timeval timeout;
WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object; WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*) Object;
fd = (pipe->ServerMode) ? pipe->serverfd : pipe->clientfd; fd = (pipe->ServerMode) ? pipe->serverfd : pipe->clientfd;
@ -432,23 +422,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
return WAIT_FAILED; return WAIT_FAILED;
} }
FD_ZERO(&rfds); status = waitOnFd(fd, dwMilliseconds);
FD_SET(fd, &rfds);
ZeroMemory(&timeout, sizeof(timeout));
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_sec = dwMilliseconds / 1000;
timeout.tv_usec = (dwMilliseconds % 1000) * 1000;
}
do
{
status = select(fd + 1, &rfds, NULL, NULL,
(dwMilliseconds == INFINITE) ? NULL : &timeout);
}
while (status < 0 && (errno == EINTR));
if (status < 0) if (status < 0)
{ {
fprintf(stderr, "WaitForSingleObject: named pipe select() failure [%d] %s\n", errno, strerror(errno)); fprintf(stderr, "WaitForSingleObject: named pipe select() failure [%d] %s\n", errno, strerror(errno));
@ -478,13 +452,17 @@ DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertabl
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds)
{ {
int fd = -1; int fd = -1;
int maxfd;
int index; int index;
int status; int status;
fd_set fds;
ULONG Type; ULONG Type;
PVOID Object; PVOID Object;
#ifdef HAVE_POLL_H
struct pollfd *pollfds;
#else
int maxfd;
fd_set fds;
struct timeval timeout; struct timeval timeout;
#endif
if (!nCount) if (!nCount)
{ {
@ -492,10 +470,15 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
return WAIT_FAILED; return WAIT_FAILED;
} }
#ifdef HAVE_POLL_H
pollfds = alloca(nCount * sizeof(struct pollfd));
#else
maxfd = 0; maxfd = 0;
FD_ZERO(&fds); FD_ZERO(&fds);
ZeroMemory(&timeout, sizeof(timeout)); ZeroMemory(&timeout, sizeof(timeout));
#endif
if (bWaitAll) if (bWaitAll)
{ {
fprintf(stderr, "WaitForMultipleObjects: bWaitAll not yet implemented\n"); fprintf(stderr, "WaitForMultipleObjects: bWaitAll not yet implemented\n");
@ -564,12 +547,25 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
return WAIT_FAILED; return WAIT_FAILED;
} }
#ifdef HAVE_POLL_H
pollfds[index].fd = fd;
pollfds[index].events = POLLIN;
pollfds[index].revents = 0;
#else
FD_SET(fd, &fds); FD_SET(fd, &fds);
if (fd > maxfd) if (fd > maxfd)
maxfd = fd; maxfd = fd;
#endif
} }
#ifdef HAVE_POLL_H
do
{
status = poll(pollfds, nCount, dwMilliseconds);
}
while (status < 0 && errno == EINTR);
#else
if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0)) if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{ {
timeout.tv_sec = dwMilliseconds / 1000; timeout.tv_sec = dwMilliseconds / 1000;
@ -582,6 +578,7 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
(dwMilliseconds == INFINITE) ? NULL : &timeout); (dwMilliseconds == INFINITE) ? NULL : &timeout);
} }
while (status < 0 && errno == EINTR); while (status < 0 && errno == EINTR);
#endif
if (status < 0) if (status < 0)
{ {
@ -615,7 +612,11 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
fd = (pipe->ServerMode) ? pipe->serverfd : pipe->clientfd; fd = (pipe->ServerMode) ? pipe->serverfd : pipe->clientfd;
} }
#ifdef HAVE_POLL_H
if (pollfds[index].revents & POLLIN)
#else
if (FD_ISSET(fd, &fds)) if (FD_ISSET(fd, &fds))
#endif
{ {
if (Type == HANDLE_TYPE_SEMAPHORE) if (Type == HANDLE_TYPE_SEMAPHORE)
{ {
@ -677,3 +678,4 @@ DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD
} }
#endif #endif

View File

@ -612,7 +612,11 @@ int _select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, cons
{ {
int status; int status;
status = select(nfds, readfds, writefds, exceptfds, (struct timeval*) timeout); do
{
status = select(nfds, readfds, writefds, exceptfds, (struct timeval*) timeout);
}
while ((status < 0) && (errno == EINTR));
return status; return status;
} }