mirror of
https://github.com/curl/curl.git
synced 2026-08-26 12:33:38 +03:00
select: use poll() if existing, avoid poll() with no sockets
poll() on macOS 10.12 was deemed broken in 2016 when we discovered that it misbehaves when provided with no sockets to wait for. The HAVE_POLL_FINE is used to mark a poll() implementation that behaves correctly: it *should* still wait the timeout time. curl has therefore opted to use select() on Apple operating systems ever since. To avoid the risk that this or other breakage cause problems. However, using select() internally is also bad because it suffers from problems when using file descriptors beyond 1024. This change makes poll() used if it is present, but if there is no sockets to wait for it avoids using poll() and instead falls back to select() - but without any sockets to wait for there is no 1024 problem. This removes all previous special-handling involving HAVE_POLL_FINE. ref: https://daniel.haxx.se/blog/2016/10/11/poll-on-mac-10-12-is-broken/ Closes #15096
This commit is contained in:
parent
72d2090fc2
commit
c72cefea0f
12 changed files with 42 additions and 165 deletions
|
|
@ -103,7 +103,7 @@
|
|||
#define USE_OPENSSL 1
|
||||
|
||||
#define HAVE_PIPE 1
|
||||
#define HAVE_POLL_FINE 1
|
||||
#define HAVE_POLL 1
|
||||
#define HAVE_POLL_H 1
|
||||
#define HAVE_PTHREAD_H 1
|
||||
#define HAVE_SETLOCALE 1
|
||||
|
|
|
|||
|
|
@ -430,8 +430,8 @@
|
|||
/* Define to 1 if you have the `eventfd' function. */
|
||||
#cmakedefine HAVE_EVENTFD 1
|
||||
|
||||
/* If you have a fine poll */
|
||||
#cmakedefine HAVE_POLL_FINE 1
|
||||
/* If you have poll */
|
||||
#cmakedefine HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#cmakedefine HAVE_POLL_H 1
|
||||
|
|
|
|||
66
lib/select.c
66
lib/select.c
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(HAVE_SELECT) && !defined(HAVE_POLL)
|
||||
#error "We cannot compile without select() or poll() support."
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
|
|
@ -32,10 +36,6 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
|
||||
#error "We cannot compile without select() or poll() support."
|
||||
#endif
|
||||
|
||||
#ifdef MSDOS
|
||||
#include <dos.h> /* delay() */
|
||||
#endif
|
||||
|
|
@ -53,16 +53,15 @@
|
|||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Internal function used for waiting a specific amount of ms
|
||||
* in Curl_socket_check() and Curl_poll() when no file descriptor
|
||||
* is provided to wait on, just being used to delay execution.
|
||||
* Winsock select() and poll() timeout mechanisms need a valid
|
||||
* socket descriptor in a not null file descriptor set to work.
|
||||
* Waiting indefinitely with this function is not allowed, a
|
||||
* zero or negative timeout value will return immediately.
|
||||
* Timeout resolution, accuracy, as well as maximum supported
|
||||
* value is system dependent, neither factor is a critical issue
|
||||
* for the intended use of this function in the library.
|
||||
* Internal function used for waiting a specific amount of ms in
|
||||
* Curl_socket_check() and Curl_poll() when no file descriptor is provided to
|
||||
* wait on, just being used to delay execution. Winsock select() and poll()
|
||||
* timeout mechanisms need a valid socket descriptor in a not null file
|
||||
* descriptor set to work. Waiting indefinitely with this function is not
|
||||
* allowed, a zero or negative timeout value will return immediately. Timeout
|
||||
* resolution, accuracy, as well as maximum supported value is system
|
||||
* dependent, neither factor is a critical issue for the intended use of this
|
||||
* function in the library.
|
||||
*
|
||||
* Return values:
|
||||
* -1 = system call error, or invalid timeout value
|
||||
|
|
@ -89,20 +88,13 @@ int Curl_wait_ms(timediff_t timeout_ms)
|
|||
#endif
|
||||
Sleep((ULONG)timeout_ms);
|
||||
#else
|
||||
#if defined(HAVE_POLL_FINE)
|
||||
/* prevent overflow, timeout_ms is typecast to int. */
|
||||
#if TIMEDIFF_T_MAX > INT_MAX
|
||||
if(timeout_ms > INT_MAX)
|
||||
timeout_ms = INT_MAX;
|
||||
#endif
|
||||
r = poll(NULL, 0, (int)timeout_ms);
|
||||
#else
|
||||
/* avoid using poll() for this since it behaves incorrectly with no sockets
|
||||
on Apple operating systems */
|
||||
{
|
||||
struct timeval pending_tv;
|
||||
r = select(0, NULL, NULL, NULL, curlx_mstotv(&pending_tv, timeout_ms));
|
||||
}
|
||||
#endif /* HAVE_POLL_FINE */
|
||||
#endif /* USE_WINSOCK */
|
||||
#endif /* _WIN32 */
|
||||
if(r) {
|
||||
if((r == -1) && (SOCKERRNO == EINTR))
|
||||
/* make EINTR from select or poll not a "lethal" error */
|
||||
|
|
@ -113,12 +105,12 @@ int Curl_wait_ms(timediff_t timeout_ms)
|
|||
return r;
|
||||
}
|
||||
|
||||
#ifndef HAVE_POLL_FINE
|
||||
#ifndef HAVE_POLL
|
||||
/*
|
||||
* This is a wrapper around select() to aid in Windows compatibility.
|
||||
* A negative timeout value makes this function wait indefinitely,
|
||||
* unless no valid file descriptor is given, when this happens the
|
||||
* negative timeout is ignored and the function times out immediately.
|
||||
* This is a wrapper around select() to aid in Windows compatibility. A
|
||||
* negative timeout value makes this function wait indefinitely, unless no
|
||||
* valid file descriptor is given, when this happens the negative timeout is
|
||||
* ignored and the function times out immediately.
|
||||
*
|
||||
* Return values:
|
||||
* -1 = system call error or fd >= FD_SETSIZE
|
||||
|
|
@ -172,13 +164,13 @@ static int our_select(curl_socket_t maxfd, /* highest socket number */
|
|||
|
||||
/*
|
||||
* Wait for read or write events on a set of file descriptors. It uses poll()
|
||||
* when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
|
||||
* when poll() is available, in order to avoid limits with FD_SETSIZE,
|
||||
* otherwise select() is used. An error is returned if select() is being used
|
||||
* and a file descriptor is too large for FD_SETSIZE.
|
||||
*
|
||||
* A negative timeout value makes this function wait indefinitely,
|
||||
* unless no valid file descriptor is given, when this happens the
|
||||
* negative timeout is ignored and the function times out immediately.
|
||||
* A negative timeout value makes this function wait indefinitely, unless no
|
||||
* valid file descriptor is given, when this happens the negative timeout is
|
||||
* ignored and the function times out immediately.
|
||||
*
|
||||
* Return values:
|
||||
* -1 = system call error or fd >= FD_SETSIZE
|
||||
|
|
@ -275,7 +267,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
|
|||
*/
|
||||
int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
|
||||
{
|
||||
#ifdef HAVE_POLL_FINE
|
||||
#ifdef HAVE_POLL
|
||||
int pending_ms;
|
||||
#else
|
||||
fd_set fds_read;
|
||||
|
|
@ -305,7 +297,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
|
|||
when function is called with a zero timeout or a negative timeout
|
||||
value indicating a blocking call should be performed. */
|
||||
|
||||
#ifdef HAVE_POLL_FINE
|
||||
#ifdef HAVE_POLL
|
||||
|
||||
/* prevent overflow, timeout_ms is typecast to int. */
|
||||
#if TIMEDIFF_T_MAX > INT_MAX
|
||||
|
|
@ -335,7 +327,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
|
|||
ufds[i].revents |= POLLIN|POLLOUT;
|
||||
}
|
||||
|
||||
#else /* HAVE_POLL_FINE */
|
||||
#else /* HAVE_POLL */
|
||||
|
||||
FD_ZERO(&fds_read);
|
||||
FD_ZERO(&fds_write);
|
||||
|
|
@ -401,7 +393,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
|
|||
r++;
|
||||
}
|
||||
|
||||
#endif /* HAVE_POLL_FINE */
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue