select.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #ifdef HAVE_SYS_SELECT_H
00026 #include <sys/select.h>
00027 #endif
00028 
00029 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
00030 #error "We can't compile without select() or poll() support."
00031 #endif
00032 
00033 #if defined(__BEOS__) && !defined(__HAIKU__)
00034 /* BeOS has FD_SET defined in socket.h */
00035 #include <socket.h>
00036 #endif
00037 
00038 #ifdef MSDOS
00039 #include <dos.h>  /* delay() */
00040 #endif
00041 
00042 #ifdef __VXWORKS__
00043 #include <strings.h>  /* bzero() in FD_SET */
00044 #endif
00045 
00046 #include <curl/curl.h>
00047 
00048 #include "urldata.h"
00049 #include "connect.h"
00050 #include "select.h"
00051 #include "warnless.h"
00052 
00053 /* Convenience local macros */
00054 #define ELAPSED_MS()  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
00055 
00056 int Curl_ack_eintr = 0;
00057 #define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
00058 
00059 /*
00060  * Internal function used for waiting a specific amount of ms
00061  * in Curl_socket_check() and Curl_poll() when no file descriptor
00062  * is provided to wait on, just being used to delay execution.
00063  * WinSock select() and poll() timeout mechanisms need a valid
00064  * socket descriptor in a not null file descriptor set to work.
00065  * Waiting indefinitely with this function is not allowed, a
00066  * zero or negative timeout value will return immediately.
00067  * Timeout resolution, accuracy, as well as maximum supported
00068  * value is system dependent, neither factor is a citical issue
00069  * for the intended use of this function in the library.
00070  *
00071  * Return values:
00072  *   -1 = system call error, invalid timeout value, or interrupted
00073  *    0 = specified timeout has elapsed
00074  */
00075 int Curl_wait_ms(int timeout_ms)
00076 {
00077 #if !defined(MSDOS) && !defined(USE_WINSOCK)
00078 #ifndef HAVE_POLL_FINE
00079   struct timeval pending_tv;
00080 #endif
00081   struct timeval initial_tv;
00082   int pending_ms;
00083   int error;
00084 #endif
00085   int r = 0;
00086 
00087   if(!timeout_ms)
00088     return 0;
00089   if(timeout_ms < 0) {
00090     SET_SOCKERRNO(EINVAL);
00091     return -1;
00092   }
00093 #if defined(MSDOS)
00094   delay(timeout_ms);
00095 #elif defined(USE_WINSOCK)
00096   Sleep(timeout_ms);
00097 #else
00098   pending_ms = timeout_ms;
00099   initial_tv = curlx_tvnow();
00100   do {
00101 #if defined(HAVE_POLL_FINE)
00102     r = poll(NULL, 0, pending_ms);
00103 #else
00104     pending_tv.tv_sec = pending_ms / 1000;
00105     pending_tv.tv_usec = (pending_ms % 1000) * 1000;
00106     r = select(0, NULL, NULL, NULL, &pending_tv);
00107 #endif /* HAVE_POLL_FINE */
00108     if(r != -1)
00109       break;
00110     error = SOCKERRNO;
00111     if(error && ERROR_NOT_EINTR(error))
00112       break;
00113     pending_ms = timeout_ms - ELAPSED_MS();
00114     if(pending_ms <= 0) {
00115       r = 0;  /* Simulate a "call timed out" case */
00116       break;
00117     }
00118   } while(r == -1);
00119 #endif /* USE_WINSOCK */
00120   if(r)
00121     r = -1;
00122   return r;
00123 }
00124 
00125 /*
00126  * Wait for read or write events on a set of file descriptors. It uses poll()
00127  * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
00128  * otherwise select() is used.  An error is returned if select() is being used
00129  * and a file descriptor is too large for FD_SETSIZE.
00130  *
00131  * A negative timeout value makes this function wait indefinitely,
00132  * unles no valid file descriptor is given, when this happens the
00133  * negative timeout is ignored and the function times out immediately.
00134  *
00135  * Return values:
00136  *   -1 = system call error or fd >= FD_SETSIZE
00137  *    0 = timeout
00138  *    [bitmask] = action as described below
00139  *
00140  * CURL_CSELECT_IN - first socket is readable
00141  * CURL_CSELECT_IN2 - second socket is readable
00142  * CURL_CSELECT_OUT - write socket is writable
00143  * CURL_CSELECT_ERR - an error condition occurred
00144  */
00145 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
00146                       curl_socket_t readfd1,
00147                       curl_socket_t writefd, /* socket to write to */
00148                       time_t timeout_ms)     /* milliseconds to wait */
00149 {
00150 #ifdef HAVE_POLL_FINE
00151   struct pollfd pfd[3];
00152   int num;
00153 #else
00154   struct timeval pending_tv;
00155   struct timeval *ptimeout;
00156   fd_set fds_read;
00157   fd_set fds_write;
00158   fd_set fds_err;
00159   curl_socket_t maxfd;
00160 #endif
00161   struct timeval initial_tv = {0, 0};
00162   int pending_ms = 0;
00163   int error;
00164   int r;
00165   int ret;
00166 
00167 #if SIZEOF_LONG != SIZEOF_INT
00168   /* wrap-around precaution */
00169   if(timeout_ms >= INT_MAX)
00170     timeout_ms = INT_MAX;
00171 #endif
00172 
00173   if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
00174      (writefd == CURL_SOCKET_BAD)) {
00175     /* no sockets, just wait */
00176     r = Curl_wait_ms((int)timeout_ms);
00177     return r;
00178   }
00179 
00180   /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
00181      time in this function does not need to be measured. This happens
00182      when function is called with a zero timeout or a negative timeout
00183      value indicating a blocking call should be performed. */
00184 
00185   if(timeout_ms > 0) {
00186     pending_ms = (int)timeout_ms;
00187     initial_tv = curlx_tvnow();
00188   }
00189 
00190 #ifdef HAVE_POLL_FINE
00191 
00192   num = 0;
00193   if(readfd0 != CURL_SOCKET_BAD) {
00194     pfd[num].fd = readfd0;
00195     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
00196     pfd[num].revents = 0;
00197     num++;
00198   }
00199   if(readfd1 != CURL_SOCKET_BAD) {
00200     pfd[num].fd = readfd1;
00201     pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
00202     pfd[num].revents = 0;
00203     num++;
00204   }
00205   if(writefd != CURL_SOCKET_BAD) {
00206     pfd[num].fd = writefd;
00207     pfd[num].events = POLLWRNORM|POLLOUT;
00208     pfd[num].revents = 0;
00209     num++;
00210   }
00211 
00212   do {
00213     if(timeout_ms < 0)
00214       pending_ms = -1;
00215     else if(!timeout_ms)
00216       pending_ms = 0;
00217     r = poll(pfd, num, pending_ms);
00218     if(r != -1)
00219       break;
00220     error = SOCKERRNO;
00221     if(error && ERROR_NOT_EINTR(error))
00222       break;
00223     if(timeout_ms > 0) {
00224       pending_ms = (int)(timeout_ms - ELAPSED_MS());
00225       if(pending_ms <= 0) {
00226         r = 0;  /* Simulate a "call timed out" case */
00227         break;
00228       }
00229     }
00230   } while(r == -1);
00231 
00232   if(r < 0)
00233     return -1;
00234   if(r == 0)
00235     return 0;
00236 
00237   ret = 0;
00238   num = 0;
00239   if(readfd0 != CURL_SOCKET_BAD) {
00240     if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
00241       ret |= CURL_CSELECT_IN;
00242     if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
00243       ret |= CURL_CSELECT_ERR;
00244     num++;
00245   }
00246   if(readfd1 != CURL_SOCKET_BAD) {
00247     if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
00248       ret |= CURL_CSELECT_IN2;
00249     if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
00250       ret |= CURL_CSELECT_ERR;
00251     num++;
00252   }
00253   if(writefd != CURL_SOCKET_BAD) {
00254     if(pfd[num].revents & (POLLWRNORM|POLLOUT))
00255       ret |= CURL_CSELECT_OUT;
00256     if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
00257       ret |= CURL_CSELECT_ERR;
00258   }
00259 
00260   return ret;
00261 
00262 #else  /* HAVE_POLL_FINE */
00263 
00264   FD_ZERO(&fds_err);
00265   maxfd = (curl_socket_t)-1;
00266 
00267   FD_ZERO(&fds_read);
00268   if(readfd0 != CURL_SOCKET_BAD) {
00269     VERIFY_SOCK(readfd0);
00270     FD_SET(readfd0, &fds_read);
00271     FD_SET(readfd0, &fds_err);
00272     maxfd = readfd0;
00273   }
00274   if(readfd1 != CURL_SOCKET_BAD) {
00275     VERIFY_SOCK(readfd1);
00276     FD_SET(readfd1, &fds_read);
00277     FD_SET(readfd1, &fds_err);
00278     if(readfd1 > maxfd)
00279       maxfd = readfd1;
00280   }
00281 
00282   FD_ZERO(&fds_write);
00283   if(writefd != CURL_SOCKET_BAD) {
00284     VERIFY_SOCK(writefd);
00285     FD_SET(writefd, &fds_write);
00286     FD_SET(writefd, &fds_err);
00287     if(writefd > maxfd)
00288       maxfd = writefd;
00289   }
00290 
00291   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
00292 
00293   do {
00294     if(timeout_ms > 0) {
00295       pending_tv.tv_sec = pending_ms / 1000;
00296       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
00297     }
00298     else if(!timeout_ms) {
00299       pending_tv.tv_sec = 0;
00300       pending_tv.tv_usec = 0;
00301     }
00302 
00303     /* WinSock select() must not be called with an fd_set that contains zero
00304        fd flags, or it will return WSAEINVAL.  But, it also can't be called
00305        with no fd_sets at all!  From the documentation:
00306 
00307          Any two of the parameters, readfds, writefds, or exceptfds, can be
00308          given as null. At least one must be non-null, and any non-null
00309          descriptor set must contain at least one handle to a socket.
00310 
00311        We know that we have at least one bit set in at least two fd_sets in
00312        this case, but we may have no bits set in either fds_read or fd_write,
00313        so check for that and handle it.  Luckily, with WinSock, we can _also_
00314        ask how many bits are set on an fd_set.
00315 
00316        It is unclear why WinSock doesn't just handle this for us instead of
00317        calling this an error.
00318 
00319        Note also that WinSock ignores the first argument, so we don't worry
00320        about the fact that maxfd is computed incorrectly with WinSock (since
00321        curl_socket_t is unsigned in such cases and thus -1 is the largest
00322        value).
00323     */
00324 #ifdef USE_WINSOCK
00325     r = select((int)maxfd + 1,
00326                fds_read.fd_count ? &fds_read : NULL,
00327                fds_write.fd_count ? &fds_write : NULL,
00328                &fds_err, ptimeout);
00329 #else
00330     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
00331 #endif
00332 
00333     if(r != -1)
00334       break;
00335     error = SOCKERRNO;
00336     if(error && ERROR_NOT_EINTR(error))
00337       break;
00338     if(timeout_ms > 0) {
00339       pending_ms = (int)(timeout_ms - ELAPSED_MS());
00340       if(pending_ms <= 0) {
00341         r = 0;  /* Simulate a "call timed out" case */
00342         break;
00343       }
00344     }
00345   } while(r == -1);
00346 
00347   if(r < 0)
00348     return -1;
00349   if(r == 0)
00350     return 0;
00351 
00352   ret = 0;
00353   if(readfd0 != CURL_SOCKET_BAD) {
00354     if(FD_ISSET(readfd0, &fds_read))
00355       ret |= CURL_CSELECT_IN;
00356     if(FD_ISSET(readfd0, &fds_err))
00357       ret |= CURL_CSELECT_ERR;
00358   }
00359   if(readfd1 != CURL_SOCKET_BAD) {
00360     if(FD_ISSET(readfd1, &fds_read))
00361       ret |= CURL_CSELECT_IN2;
00362     if(FD_ISSET(readfd1, &fds_err))
00363       ret |= CURL_CSELECT_ERR;
00364   }
00365   if(writefd != CURL_SOCKET_BAD) {
00366     if(FD_ISSET(writefd, &fds_write))
00367       ret |= CURL_CSELECT_OUT;
00368     if(FD_ISSET(writefd, &fds_err))
00369       ret |= CURL_CSELECT_ERR;
00370   }
00371 
00372   return ret;
00373 
00374 #endif  /* HAVE_POLL_FINE */
00375 
00376 }
00377 
00378 /*
00379  * This is a wrapper around poll().  If poll() does not exist, then
00380  * select() is used instead.  An error is returned if select() is
00381  * being used and a file descriptor is too large for FD_SETSIZE.
00382  * A negative timeout value makes this function wait indefinitely,
00383  * unles no valid file descriptor is given, when this happens the
00384  * negative timeout is ignored and the function times out immediately.
00385  *
00386  * Return values:
00387  *   -1 = system call error or fd >= FD_SETSIZE
00388  *    0 = timeout
00389  *    N = number of structures with non zero revent fields
00390  */
00391 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
00392 {
00393 #ifndef HAVE_POLL_FINE
00394   struct timeval pending_tv;
00395   struct timeval *ptimeout;
00396   fd_set fds_read;
00397   fd_set fds_write;
00398   fd_set fds_err;
00399   curl_socket_t maxfd;
00400 #endif
00401   struct timeval initial_tv = {0, 0};
00402   bool fds_none = TRUE;
00403   unsigned int i;
00404   int pending_ms = 0;
00405   int error;
00406   int r;
00407 
00408   if(ufds) {
00409     for(i = 0; i < nfds; i++) {
00410       if(ufds[i].fd != CURL_SOCKET_BAD) {
00411         fds_none = FALSE;
00412         break;
00413       }
00414     }
00415   }
00416   if(fds_none) {
00417     r = Curl_wait_ms(timeout_ms);
00418     return r;
00419   }
00420 
00421   /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
00422      time in this function does not need to be measured. This happens
00423      when function is called with a zero timeout or a negative timeout
00424      value indicating a blocking call should be performed. */
00425 
00426   if(timeout_ms > 0) {
00427     pending_ms = timeout_ms;
00428     initial_tv = curlx_tvnow();
00429   }
00430 
00431 #ifdef HAVE_POLL_FINE
00432 
00433   do {
00434     if(timeout_ms < 0)
00435       pending_ms = -1;
00436     else if(!timeout_ms)
00437       pending_ms = 0;
00438     r = poll(ufds, nfds, pending_ms);
00439     if(r != -1)
00440       break;
00441     error = SOCKERRNO;
00442     if(error && ERROR_NOT_EINTR(error))
00443       break;
00444     if(timeout_ms > 0) {
00445       pending_ms = (int)(timeout_ms - ELAPSED_MS());
00446       if(pending_ms <= 0) {
00447         r = 0;  /* Simulate a "call timed out" case */
00448         break;
00449       }
00450     }
00451   } while(r == -1);
00452 
00453   if(r < 0)
00454     return -1;
00455   if(r == 0)
00456     return 0;
00457 
00458   for(i = 0; i < nfds; i++) {
00459     if(ufds[i].fd == CURL_SOCKET_BAD)
00460       continue;
00461     if(ufds[i].revents & POLLHUP)
00462       ufds[i].revents |= POLLIN;
00463     if(ufds[i].revents & POLLERR)
00464       ufds[i].revents |= (POLLIN|POLLOUT);
00465   }
00466 
00467 #else  /* HAVE_POLL_FINE */
00468 
00469   FD_ZERO(&fds_read);
00470   FD_ZERO(&fds_write);
00471   FD_ZERO(&fds_err);
00472   maxfd = (curl_socket_t)-1;
00473 
00474   for(i = 0; i < nfds; i++) {
00475     ufds[i].revents = 0;
00476     if(ufds[i].fd == CURL_SOCKET_BAD)
00477       continue;
00478     VERIFY_SOCK(ufds[i].fd);
00479     if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
00480                           POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
00481       if(ufds[i].fd > maxfd)
00482         maxfd = ufds[i].fd;
00483       if(ufds[i].events & (POLLRDNORM|POLLIN))
00484         FD_SET(ufds[i].fd, &fds_read);
00485       if(ufds[i].events & (POLLWRNORM|POLLOUT))
00486         FD_SET(ufds[i].fd, &fds_write);
00487       if(ufds[i].events & (POLLRDBAND|POLLPRI))
00488         FD_SET(ufds[i].fd, &fds_err);
00489     }
00490   }
00491 
00492 #ifdef USE_WINSOCK
00493   /* WinSock select() can't handle zero events.  See the comment about this in
00494      Curl_check_socket(). */
00495   if(fds_read.fd_count == 0 && fds_write.fd_count == 0
00496      && fds_err.fd_count == 0) {
00497     r = Curl_wait_ms(timeout_ms);
00498     return r;
00499   }
00500 #endif
00501 
00502   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
00503 
00504   do {
00505     if(timeout_ms > 0) {
00506       pending_tv.tv_sec = pending_ms / 1000;
00507       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
00508     }
00509     else if(!timeout_ms) {
00510       pending_tv.tv_sec = 0;
00511       pending_tv.tv_usec = 0;
00512     }
00513 
00514 #ifdef USE_WINSOCK
00515     r = select((int)maxfd + 1,
00516                /* WinSock select() can't handle fd_sets with zero bits set, so
00517                   don't give it such arguments.  See the comment about this in
00518                   Curl_check_socket().
00519                */
00520                fds_read.fd_count ? &fds_read : NULL,
00521                fds_write.fd_count ? &fds_write : NULL,
00522                fds_err.fd_count ? &fds_err : NULL, ptimeout);
00523 #else
00524     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
00525 #endif
00526     if(r != -1)
00527       break;
00528     error = SOCKERRNO;
00529     if(error && ERROR_NOT_EINTR(error))
00530       break;
00531     if(timeout_ms > 0) {
00532       pending_ms = timeout_ms - ELAPSED_MS();
00533       if(pending_ms <= 0) {
00534         r = 0;  /* Simulate a "call timed out" case */
00535         break;
00536       }
00537     }
00538   } while(r == -1);
00539 
00540   if(r < 0)
00541     return -1;
00542   if(r == 0)
00543     return 0;
00544 
00545   r = 0;
00546   for(i = 0; i < nfds; i++) {
00547     ufds[i].revents = 0;
00548     if(ufds[i].fd == CURL_SOCKET_BAD)
00549       continue;
00550     if(FD_ISSET(ufds[i].fd, &fds_read))
00551       ufds[i].revents |= POLLIN;
00552     if(FD_ISSET(ufds[i].fd, &fds_write))
00553       ufds[i].revents |= POLLOUT;
00554     if(FD_ISSET(ufds[i].fd, &fds_err))
00555       ufds[i].revents |= POLLPRI;
00556     if(ufds[i].revents != 0)
00557       r++;
00558   }
00559 
00560 #endif  /* HAVE_POLL_FINE */
00561 
00562   return r;
00563 }
00564 
00565 #ifdef TPF
00566 /*
00567  * This is a replacement for select() on the TPF platform.
00568  * It is used whenever libcurl calls select().
00569  * The call below to tpf_process_signals() is required because
00570  * TPF's select calls are not signal interruptible.
00571  *
00572  * Return values are the same as select's.
00573  */
00574 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
00575                        fd_set* excepts, struct timeval* tv)
00576 {
00577    int rc;
00578 
00579    rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
00580    tpf_process_signals();
00581    return rc;
00582 }
00583 #endif /* TPF */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06