select.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at http://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. #include "setup.h"
  23. #ifdef HAVE_SYS_SELECT_H
  24. #include <sys/select.h>
  25. #endif
  26. #ifdef HAVE_SYS_TIME_H
  27. #include <sys/time.h>
  28. #endif
  29. #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
  30. #error "We can't compile without select() or poll() support."
  31. #endif
  32. #if defined(__BEOS__) && !defined(__HAIKU__)
  33. /* BeOS has FD_SET defined in socket.h */
  34. #include <socket.h>
  35. #endif
  36. #ifdef MSDOS
  37. #include <dos.h> /* delay() */
  38. #endif
  39. #include <curl/curl.h>
  40. #include "urldata.h"
  41. #include "connect.h"
  42. #include "select.h"
  43. /* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
  44. #if defined(USE_WINSOCK) || defined(TPF)
  45. #define VERIFY_SOCK(x) do { } while(0)
  46. #else
  47. #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
  48. #define VERIFY_SOCK(x) do { \
  49. if(!VALID_SOCK(x)) { \
  50. SET_SOCKERRNO(EINVAL); \
  51. return -1; \
  52. } \
  53. } while(0)
  54. #endif
  55. /* Convenience local macros */
  56. #define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
  57. #ifdef CURL_ACKNOWLEDGE_EINTR
  58. #define error_not_EINTR (1)
  59. #else
  60. #define error_not_EINTR (error != EINTR)
  61. #endif
  62. /*
  63. * Internal function used for waiting a specific amount of ms
  64. * in Curl_socket_ready() and Curl_poll() when no file descriptor
  65. * is provided to wait on, just being used to delay execution.
  66. * WinSock select() and poll() timeout mechanisms need a valid
  67. * socket descriptor in a not null file descriptor set to work.
  68. * Waiting indefinitely with this function is not allowed, a
  69. * zero or negative timeout value will return immediately.
  70. * Timeout resolution, accuracy, as well as maximum supported
  71. * value is system dependent, neither factor is a citical issue
  72. * for the intended use of this function in the library.
  73. * On non-DOS and non-Winsock platforms, when compiled with
  74. * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored
  75. * and function might exit early without awaiting full timeout,
  76. * otherwise EINTR will be ignored and full timeout will elapse.
  77. *
  78. * Return values:
  79. * -1 = system call error, invalid timeout value, or interrupted
  80. * 0 = specified timeout has elapsed
  81. */
  82. static int wait_ms(int timeout_ms)
  83. {
  84. #if !defined(MSDOS) && !defined(USE_WINSOCK)
  85. #ifndef HAVE_POLL_FINE
  86. struct timeval pending_tv;
  87. #endif
  88. struct timeval initial_tv;
  89. int pending_ms;
  90. int error;
  91. #endif
  92. int r = 0;
  93. if(!timeout_ms)
  94. return 0;
  95. if(timeout_ms < 0) {
  96. SET_SOCKERRNO(EINVAL);
  97. return -1;
  98. }
  99. #if defined(MSDOS)
  100. delay(timeout_ms);
  101. #elif defined(USE_WINSOCK)
  102. Sleep(timeout_ms);
  103. #else
  104. pending_ms = timeout_ms;
  105. initial_tv = curlx_tvnow();
  106. do {
  107. #if defined(HAVE_POLL_FINE)
  108. r = poll(NULL, 0, pending_ms);
  109. #else
  110. pending_tv.tv_sec = pending_ms / 1000;
  111. pending_tv.tv_usec = (pending_ms % 1000) * 1000;
  112. r = select(0, NULL, NULL, NULL, &pending_tv);
  113. #endif /* HAVE_POLL_FINE */
  114. if(r != -1)
  115. break;
  116. error = SOCKERRNO;
  117. if(error && error_not_EINTR)
  118. break;
  119. pending_ms = timeout_ms - elapsed_ms;
  120. if(pending_ms <= 0)
  121. break;
  122. } while(r == -1);
  123. #endif /* USE_WINSOCK */
  124. if(r)
  125. r = -1;
  126. return r;
  127. }
  128. /*
  129. * This is an internal function used for waiting for read or write
  130. * events on a pair of file descriptors. It uses poll() when a fine
  131. * poll() is available, in order to avoid limits with FD_SETSIZE,
  132. * otherwise select() is used. An error is returned if select() is
  133. * being used and a file descriptor is too large for FD_SETSIZE.
  134. * A negative timeout value makes this function wait indefinitely,
  135. * unles no valid file descriptor is given, when this happens the
  136. * negative timeout is ignored and the function times out immediately.
  137. * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
  138. * is honored and function might exit early without awaiting timeout,
  139. * otherwise EINTR will be ignored.
  140. *
  141. * Return values:
  142. * -1 = system call error or fd >= FD_SETSIZE
  143. * 0 = timeout
  144. * CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR
  145. */
  146. int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
  147. int timeout_ms)
  148. {
  149. #ifdef HAVE_POLL_FINE
  150. struct pollfd pfd[2];
  151. int num;
  152. #else
  153. struct timeval pending_tv;
  154. struct timeval *ptimeout;
  155. fd_set fds_read;
  156. fd_set fds_write;
  157. fd_set fds_err;
  158. curl_socket_t maxfd;
  159. #endif
  160. struct timeval initial_tv = {0,0};
  161. int pending_ms = 0;
  162. int error;
  163. int r;
  164. int ret;
  165. if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
  166. r = wait_ms(timeout_ms);
  167. return r;
  168. }
  169. /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
  170. time in this function does not need to be measured. This happens
  171. when function is called with a zero timeout or a negative timeout
  172. value indicating a blocking call should be performed. */
  173. if(timeout_ms > 0) {
  174. pending_ms = timeout_ms;
  175. initial_tv = curlx_tvnow();
  176. }
  177. #ifdef HAVE_POLL_FINE
  178. num = 0;
  179. if(readfd != CURL_SOCKET_BAD) {
  180. pfd[num].fd = readfd;
  181. pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
  182. pfd[num].revents = 0;
  183. num++;
  184. }
  185. if(writefd != CURL_SOCKET_BAD) {
  186. pfd[num].fd = writefd;
  187. pfd[num].events = POLLWRNORM|POLLOUT;
  188. pfd[num].revents = 0;
  189. num++;
  190. }
  191. do {
  192. if(timeout_ms < 0)
  193. pending_ms = -1;
  194. else if(!timeout_ms)
  195. pending_ms = 0;
  196. r = poll(pfd, num, pending_ms);
  197. if(r != -1)
  198. break;
  199. error = SOCKERRNO;
  200. if(error && error_not_EINTR)
  201. break;
  202. if(timeout_ms > 0) {
  203. pending_ms = timeout_ms - elapsed_ms;
  204. if(pending_ms <= 0)
  205. break;
  206. }
  207. } while(r == -1);
  208. if(r < 0)
  209. return -1;
  210. if(r == 0)
  211. return 0;
  212. ret = 0;
  213. num = 0;
  214. if(readfd != CURL_SOCKET_BAD) {
  215. if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
  216. ret |= CURL_CSELECT_IN;
  217. if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
  218. ret |= CURL_CSELECT_ERR;
  219. num++;
  220. }
  221. if(writefd != CURL_SOCKET_BAD) {
  222. if(pfd[num].revents & (POLLWRNORM|POLLOUT))
  223. ret |= CURL_CSELECT_OUT;
  224. if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
  225. ret |= CURL_CSELECT_ERR;
  226. }
  227. return ret;
  228. #else /* HAVE_POLL_FINE */
  229. FD_ZERO(&fds_err);
  230. maxfd = (curl_socket_t)-1;
  231. FD_ZERO(&fds_read);
  232. if(readfd != CURL_SOCKET_BAD) {
  233. VERIFY_SOCK(readfd);
  234. FD_SET(readfd, &fds_read);
  235. FD_SET(readfd, &fds_err);
  236. maxfd = readfd;
  237. }
  238. FD_ZERO(&fds_write);
  239. if(writefd != CURL_SOCKET_BAD) {
  240. VERIFY_SOCK(writefd);
  241. FD_SET(writefd, &fds_write);
  242. FD_SET(writefd, &fds_err);
  243. if(writefd > maxfd)
  244. maxfd = writefd;
  245. }
  246. ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
  247. do {
  248. if(timeout_ms > 0) {
  249. pending_tv.tv_sec = pending_ms / 1000;
  250. pending_tv.tv_usec = (pending_ms % 1000) * 1000;
  251. }
  252. else if(!timeout_ms) {
  253. pending_tv.tv_sec = 0;
  254. pending_tv.tv_usec = 0;
  255. }
  256. r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
  257. if(r != -1)
  258. break;
  259. error = SOCKERRNO;
  260. if(error && error_not_EINTR)
  261. break;
  262. if(timeout_ms > 0) {
  263. pending_ms = timeout_ms - elapsed_ms;
  264. if(pending_ms <= 0)
  265. break;
  266. }
  267. } while(r == -1);
  268. if(r < 0)
  269. return -1;
  270. if(r == 0)
  271. return 0;
  272. ret = 0;
  273. if(readfd != CURL_SOCKET_BAD) {
  274. if(FD_ISSET(readfd, &fds_read))
  275. ret |= CURL_CSELECT_IN;
  276. if(FD_ISSET(readfd, &fds_err))
  277. ret |= CURL_CSELECT_ERR;
  278. }
  279. if(writefd != CURL_SOCKET_BAD) {
  280. if(FD_ISSET(writefd, &fds_write))
  281. ret |= CURL_CSELECT_OUT;
  282. if(FD_ISSET(writefd, &fds_err))
  283. ret |= CURL_CSELECT_ERR;
  284. }
  285. return ret;
  286. #endif /* HAVE_POLL_FINE */
  287. }
  288. /*
  289. * This is a wrapper around poll(). If poll() does not exist, then
  290. * select() is used instead. An error is returned if select() is
  291. * being used and a file descriptor is too large for FD_SETSIZE.
  292. * A negative timeout value makes this function wait indefinitely,
  293. * unles no valid file descriptor is given, when this happens the
  294. * negative timeout is ignored and the function times out immediately.
  295. * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
  296. * is honored and function might exit early without awaiting timeout,
  297. * otherwise EINTR will be ignored.
  298. *
  299. * Return values:
  300. * -1 = system call error or fd >= FD_SETSIZE
  301. * 0 = timeout
  302. * N = number of structures with non zero revent fields
  303. */
  304. int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
  305. {
  306. #ifndef HAVE_POLL_FINE
  307. struct timeval pending_tv;
  308. struct timeval *ptimeout;
  309. fd_set fds_read;
  310. fd_set fds_write;
  311. fd_set fds_err;
  312. curl_socket_t maxfd;
  313. #endif
  314. struct timeval initial_tv = {0,0};
  315. bool fds_none = TRUE;
  316. unsigned int i;
  317. int pending_ms = 0;
  318. int error;
  319. int r;
  320. if(ufds) {
  321. for (i = 0; i < nfds; i++) {
  322. if(ufds[i].fd != CURL_SOCKET_BAD) {
  323. fds_none = FALSE;
  324. break;
  325. }
  326. }
  327. }
  328. if(fds_none) {
  329. r = wait_ms(timeout_ms);
  330. return r;
  331. }
  332. /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
  333. time in this function does not need to be measured. This happens
  334. when function is called with a zero timeout or a negative timeout
  335. value indicating a blocking call should be performed. */
  336. if(timeout_ms > 0) {
  337. pending_ms = timeout_ms;
  338. initial_tv = curlx_tvnow();
  339. }
  340. #ifdef HAVE_POLL_FINE
  341. do {
  342. if(timeout_ms < 0)
  343. pending_ms = -1;
  344. else if(!timeout_ms)
  345. pending_ms = 0;
  346. r = poll(ufds, nfds, pending_ms);
  347. if(r != -1)
  348. break;
  349. error = SOCKERRNO;
  350. if(error && error_not_EINTR)
  351. break;
  352. if(timeout_ms > 0) {
  353. pending_ms = timeout_ms - elapsed_ms;
  354. if(pending_ms <= 0)
  355. break;
  356. }
  357. } while(r == -1);
  358. if(r < 0)
  359. return -1;
  360. if(r == 0)
  361. return 0;
  362. for (i = 0; i < nfds; i++) {
  363. if(ufds[i].fd == CURL_SOCKET_BAD)
  364. continue;
  365. if(ufds[i].revents & POLLHUP)
  366. ufds[i].revents |= POLLIN;
  367. if(ufds[i].revents & POLLERR)
  368. ufds[i].revents |= (POLLIN|POLLOUT);
  369. }
  370. #else /* HAVE_POLL_FINE */
  371. FD_ZERO(&fds_read);
  372. FD_ZERO(&fds_write);
  373. FD_ZERO(&fds_err);
  374. maxfd = (curl_socket_t)-1;
  375. for (i = 0; i < nfds; i++) {
  376. ufds[i].revents = 0;
  377. if(ufds[i].fd == CURL_SOCKET_BAD)
  378. continue;
  379. VERIFY_SOCK(ufds[i].fd);
  380. if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
  381. POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
  382. if(ufds[i].fd > maxfd)
  383. maxfd = ufds[i].fd;
  384. if(ufds[i].events & (POLLRDNORM|POLLIN))
  385. FD_SET(ufds[i].fd, &fds_read);
  386. if(ufds[i].events & (POLLWRNORM|POLLOUT))
  387. FD_SET(ufds[i].fd, &fds_write);
  388. if(ufds[i].events & (POLLRDBAND|POLLPRI))
  389. FD_SET(ufds[i].fd, &fds_err);
  390. }
  391. }
  392. ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
  393. do {
  394. if(timeout_ms > 0) {
  395. pending_tv.tv_sec = pending_ms / 1000;
  396. pending_tv.tv_usec = (pending_ms % 1000) * 1000;
  397. }
  398. else if(!timeout_ms) {
  399. pending_tv.tv_sec = 0;
  400. pending_tv.tv_usec = 0;
  401. }
  402. r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
  403. if(r != -1)
  404. break;
  405. error = SOCKERRNO;
  406. if(error && error_not_EINTR)
  407. break;
  408. if(timeout_ms > 0) {
  409. pending_ms = timeout_ms - elapsed_ms;
  410. if(pending_ms <= 0)
  411. break;
  412. }
  413. } while(r == -1);
  414. if(r < 0)
  415. return -1;
  416. if(r == 0)
  417. return 0;
  418. r = 0;
  419. for (i = 0; i < nfds; i++) {
  420. ufds[i].revents = 0;
  421. if(ufds[i].fd == CURL_SOCKET_BAD)
  422. continue;
  423. if(FD_ISSET(ufds[i].fd, &fds_read))
  424. ufds[i].revents |= POLLIN;
  425. if(FD_ISSET(ufds[i].fd, &fds_write))
  426. ufds[i].revents |= POLLOUT;
  427. if(FD_ISSET(ufds[i].fd, &fds_err))
  428. ufds[i].revents |= POLLPRI;
  429. if(ufds[i].revents != 0)
  430. r++;
  431. }
  432. #endif /* HAVE_POLL_FINE */
  433. return r;
  434. }
  435. #ifdef TPF
  436. /*
  437. * This is a replacement for select() on the TPF platform.
  438. * It is used whenever libcurl calls select().
  439. * The call below to tpf_process_signals() is required because
  440. * TPF's select calls are not signal interruptible.
  441. *
  442. * Return values are the same as select's.
  443. */
  444. int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
  445. fd_set* excepts, struct timeval* tv)
  446. {
  447. int rc;
  448. rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
  449. tpf_process_signals();
  450. return(rc);
  451. }
  452. #endif /* TPF */