diff options
author | Bertrand SIMONNET <bsimonnet@google.com> | 2015-07-01 15:39:44 -0700 |
---|---|---|
committer | Bertrand SIMONNET <bsimonnet@google.com> | 2015-07-08 10:51:12 -0700 |
commit | e6cd738ed3716c02557fb3a47515244e949ade39 (patch) | |
tree | 8d093306c27b850f828317ed67d6efea3ec7e084 /lib/select.c | |
parent | d43abe883892fe84137052fd27ecd956a2c7cacf (diff) | |
download | android_external_curl-e6cd738ed3716c02557fb3a47515244e949ade39.tar.gz android_external_curl-e6cd738ed3716c02557fb3a47515244e949ade39.tar.bz2 android_external_curl-e6cd738ed3716c02557fb3a47515244e949ade39.zip |
Import curl 7.43
This is a simple import of curl 7.43.
The only change from the official release is the fact that the
Android.mk was removed to avoid build error trying to parse it.
BUG: 22347561
Change-Id: I52ef6798d30b25d22d1f62770d571adec8bcf4d5
Diffstat (limited to 'lib/select.c')
-rw-r--r-- | lib/select.c | 220 |
1 files changed, 146 insertions, 74 deletions
diff --git a/lib/select.c b/lib/select.c index e6882da..24dc5fd 100644 --- a/lib/select.c +++ b/lib/select.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -20,14 +20,11 @@ * ***************************************************************************/ -#include "setup.h" +#include "curl_setup.h" #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) #error "We can't compile without select() or poll() support." @@ -42,35 +39,23 @@ #include <dos.h> /* delay() */ #endif +#ifdef __VXWORKS__ +#include <strings.h> /* bzero() in FD_SET */ +#endif + #include <curl/curl.h> #include "urldata.h" #include "connect.h" #include "select.h" - -/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */ - -#if defined(USE_WINSOCK) || defined(TPF) -#define VERIFY_SOCK(x) do { } while(0) -#else -#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) -#define VERIFY_SOCK(x) do { \ - if(!VALID_SOCK(x)) { \ - SET_SOCKERRNO(EINVAL); \ - return -1; \ - } \ -} while(0) -#endif +#include "warnless.h" /* Convenience local macros */ #define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv) -#ifdef CURL_ACKNOWLEDGE_EINTR -#define error_not_EINTR (1) -#else -#define error_not_EINTR (error != EINTR) -#endif +int Curl_ack_eintr = 0; +#define error_not_EINTR (Curl_ack_eintr || error != EINTR) /* * Internal function used for waiting a specific amount of ms @@ -83,16 +68,12 @@ * Timeout resolution, accuracy, as well as maximum supported * value is system dependent, neither factor is a citical issue * for the intended use of this function in the library. - * On non-DOS and non-Winsock platforms, when compiled with - * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored - * and function might exit early without awaiting full timeout, - * otherwise EINTR will be ignored and full timeout will elapse. * * Return values: * -1 = system call error, invalid timeout value, or interrupted * 0 = specified timeout has elapsed */ -static int wait_ms(int timeout_ms) +int Curl_wait_ms(int timeout_ms) { #if !defined(MSDOS) && !defined(USE_WINSOCK) #ifndef HAVE_POLL_FINE @@ -131,8 +112,10 @@ static int wait_ms(int timeout_ms) if(error && error_not_EINTR) break; pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ break; + } } while(r == -1); #endif /* USE_WINSOCK */ if(r) @@ -141,28 +124,32 @@ static int wait_ms(int timeout_ms) } /* - * This is an internal function used for waiting for read or write - * events on a pair of file descriptors. It uses poll() when a fine - * 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. + * 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, + * 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, * unles no valid file descriptor is given, when this happens the * negative timeout is ignored and the function times out immediately. - * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition - * is honored and function might exit early without awaiting timeout, - * otherwise EINTR will be ignored. * * Return values: * -1 = system call error or fd >= FD_SETSIZE * 0 = timeout - * CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR + * [bitmask] = action as described below + * + * CURL_CSELECT_IN - first socket is readable + * CURL_CSELECT_IN2 - second socket is readable + * CURL_CSELECT_OUT - write socket is writable + * CURL_CSELECT_ERR - an error condition occurred */ -int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, - int timeout_ms) +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + curl_socket_t readfd1, + curl_socket_t writefd, /* socket to write to */ + long timeout_ms) /* milliseconds to wait */ { #ifdef HAVE_POLL_FINE - struct pollfd pfd[2]; + struct pollfd pfd[3]; int num; #else struct timeval pending_tv; @@ -172,14 +159,16 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, fd_set fds_err; curl_socket_t maxfd; #endif - struct timeval initial_tv = {0,0}; + struct timeval initial_tv = {0, 0}; int pending_ms = 0; int error; int r; int ret; - if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) { - r = wait_ms(timeout_ms); + if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && + (writefd == CURL_SOCKET_BAD)) { + /* no sockets, just wait */ + r = Curl_wait_ms((int)timeout_ms); return r; } @@ -189,15 +178,21 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, value indicating a blocking call should be performed. */ if(timeout_ms > 0) { - pending_ms = timeout_ms; + pending_ms = (int)timeout_ms; initial_tv = curlx_tvnow(); } #ifdef HAVE_POLL_FINE num = 0; - if(readfd != CURL_SOCKET_BAD) { - pfd[num].fd = readfd; + if(readfd0 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd0; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd1; pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; pfd[num].revents = 0; num++; @@ -221,9 +216,11 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, if(error && error_not_EINTR) break; if(timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) + pending_ms = (int)(timeout_ms - elapsed_ms); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ break; + } } } while(r == -1); @@ -234,13 +231,20 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, ret = 0; num = 0; - if(readfd != CURL_SOCKET_BAD) { + if(readfd0 != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) ret |= CURL_CSELECT_IN; if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) ret |= CURL_CSELECT_ERR; num++; } + if(readfd1 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN2; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } if(writefd != CURL_SOCKET_BAD) { if(pfd[num].revents & (POLLWRNORM|POLLOUT)) ret |= CURL_CSELECT_OUT; @@ -256,11 +260,18 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, maxfd = (curl_socket_t)-1; FD_ZERO(&fds_read); - if(readfd != CURL_SOCKET_BAD) { - VERIFY_SOCK(readfd); - FD_SET(readfd, &fds_read); - FD_SET(readfd, &fds_err); - maxfd = readfd; + if(readfd0 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd0); + FD_SET(readfd0, &fds_read); + FD_SET(readfd0, &fds_err); + maxfd = readfd0; + } + if(readfd1 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd1); + FD_SET(readfd1, &fds_read); + FD_SET(readfd1, &fds_err); + if(readfd1 > maxfd) + maxfd = readfd1; } FD_ZERO(&fds_write); @@ -283,7 +294,37 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, pending_tv.tv_sec = 0; pending_tv.tv_usec = 0; } - r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); + + /* WinSock select() must not be called with an fd_set that contains zero + fd flags, or it will return WSAEINVAL. But, it also can't be called + with no fd_sets at all! From the documentation: + + Any two of the parameters, readfds, writefds, or exceptfds, can be + given as null. At least one must be non-null, and any non-null + descriptor set must contain at least one handle to a socket. + + We know that we have at least one bit set in at least two fd_sets in + this case, but we may have no bits set in either fds_read or fd_write, + so check for that and handle it. Luckily, with WinSock, we can _also_ + ask how many bits are set on an fd_set. + + It is unclear why WinSock doesn't just handle this for us instead of + calling this an error. + + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ + r = select((int)maxfd + 1, +#ifndef USE_WINSOCK + &fds_read, + &fds_write, +#else + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, +#endif + &fds_err, ptimeout); if(r != -1) break; error = SOCKERRNO; @@ -291,8 +332,10 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, break; if(timeout_ms > 0) { pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ break; + } } } while(r == -1); @@ -302,10 +345,16 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, return 0; ret = 0; - if(readfd != CURL_SOCKET_BAD) { - if(FD_ISSET(readfd, &fds_read)) + if(readfd0 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd0, &fds_read)) ret |= CURL_CSELECT_IN; - if(FD_ISSET(readfd, &fds_err)) + if(FD_ISSET(readfd0, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd1, &fds_read)) + ret |= CURL_CSELECT_IN2; + if(FD_ISSET(readfd1, &fds_err)) ret |= CURL_CSELECT_ERR; } if(writefd != CURL_SOCKET_BAD) { @@ -328,9 +377,6 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, * A negative timeout value makes this function wait indefinitely, * unles no valid file descriptor is given, when this happens the * negative timeout is ignored and the function times out immediately. - * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition - * is honored and function might exit early without awaiting timeout, - * otherwise EINTR will be ignored. * * Return values: * -1 = system call error or fd >= FD_SETSIZE @@ -347,7 +393,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) fd_set fds_err; curl_socket_t maxfd; #endif - struct timeval initial_tv = {0,0}; + struct timeval initial_tv = {0, 0}; bool fds_none = TRUE; unsigned int i; int pending_ms = 0; @@ -355,7 +401,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) int r; if(ufds) { - for (i = 0; i < nfds; i++) { + for(i = 0; i < nfds; i++) { if(ufds[i].fd != CURL_SOCKET_BAD) { fds_none = FALSE; break; @@ -363,7 +409,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) } } if(fds_none) { - r = wait_ms(timeout_ms); + r = Curl_wait_ms(timeout_ms); return r; } @@ -392,8 +438,10 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) break; if(timeout_ms > 0) { pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ break; + } } } while(r == -1); @@ -402,7 +450,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) if(r == 0) return 0; - for (i = 0; i < nfds; i++) { + for(i = 0; i < nfds; i++) { if(ufds[i].fd == CURL_SOCKET_BAD) continue; if(ufds[i].revents & POLLHUP) @@ -418,7 +466,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) FD_ZERO(&fds_err); maxfd = (curl_socket_t)-1; - for (i = 0; i < nfds; i++) { + for(i = 0; i < nfds; i++) { ufds[i].revents = 0; if(ufds[i].fd == CURL_SOCKET_BAD) continue; @@ -436,6 +484,16 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) } } +#ifdef USE_WINSOCK + /* WinSock select() can't handle zero events. See the comment about this in + Curl_check_socket(). */ + if(fds_read.fd_count == 0 && fds_write.fd_count == 0 + && fds_err.fd_count == 0) { + r = Curl_wait_ms(timeout_ms); + return r; + } +#endif + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; do { @@ -447,7 +505,19 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) pending_tv.tv_sec = 0; pending_tv.tv_usec = 0; } - r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); + r = select((int)maxfd + 1, +#ifndef USE_WINSOCK + &fds_read, &fds_write, &fds_err, +#else + /* WinSock select() can't handle fd_sets with zero bits set, so + don't give it such arguments. See the comment about this in + Curl_check_socket(). + */ + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + fds_err.fd_count ? &fds_err : NULL, +#endif + ptimeout); if(r != -1) break; error = SOCKERRNO; @@ -455,8 +525,10 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) break; if(timeout_ms > 0) { pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ break; + } } } while(r == -1); @@ -466,7 +538,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) return 0; r = 0; - for (i = 0; i < nfds; i++) { + for(i = 0; i < nfds; i++) { ufds[i].revents = 0; if(ufds[i].fd == CURL_SOCKET_BAD) continue; @@ -501,6 +573,6 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); tpf_process_signals(); - return(rc); + return rc; } #endif /* TPF */ |