select.c (14406B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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 https://curl.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #if !defined(HAVE_SELECT) && !defined(HAVE_POLL) 28 #error "We cannot compile without select() or poll() support." 29 #endif 30 31 #include <limits.h> 32 33 #ifdef HAVE_SYS_SELECT_H 34 #include <sys/select.h> 35 #elif defined(HAVE_UNISTD_H) 36 #include <unistd.h> 37 #endif 38 39 #include <curl/curl.h> 40 41 #include "urldata.h" 42 #include "connect.h" 43 #include "select.h" 44 #include "curlx/timediff.h" 45 #include "curlx/wait.h" 46 #include "curlx/warnless.h" 47 /* The last 3 #include files should be in this order */ 48 #include "curl_printf.h" 49 #include "curl_memory.h" 50 #include "memdebug.h" 51 52 #ifndef HAVE_POLL 53 /* 54 * This is a wrapper around select() to aid in Windows compatibility. A 55 * negative timeout value makes this function wait indefinitely, unless no 56 * valid file descriptor is given, when this happens the negative timeout is 57 * ignored and the function times out immediately. 58 * 59 * Return values: 60 * -1 = system call error or fd >= FD_SETSIZE 61 * 0 = timeout 62 * N = number of signalled file descriptors 63 */ 64 static int our_select(curl_socket_t maxfd, /* highest socket number */ 65 fd_set *fds_read, /* sockets ready for reading */ 66 fd_set *fds_write, /* sockets ready for writing */ 67 fd_set *fds_err, /* sockets with errors */ 68 timediff_t timeout_ms) /* milliseconds to wait */ 69 { 70 struct timeval pending_tv; 71 struct timeval *ptimeout; 72 73 #ifdef USE_WINSOCK 74 /* Winsock select() cannot handle zero events. See the comment below. */ 75 if((!fds_read || fds_read->fd_count == 0) && 76 (!fds_write || fds_write->fd_count == 0) && 77 (!fds_err || fds_err->fd_count == 0)) { 78 /* no sockets, just wait */ 79 return curlx_wait_ms(timeout_ms); 80 } 81 #endif 82 83 ptimeout = curlx_mstotv(&pending_tv, timeout_ms); 84 85 #ifdef USE_WINSOCK 86 /* Winsock select() must not be called with an fd_set that contains zero 87 fd flags, or it will return WSAEINVAL. But, it also cannot be called 88 with no fd_sets at all! From the documentation: 89 90 Any two of the parameters, readfds, writefds, or exceptfds, can be 91 given as null. At least one must be non-null, and any non-null 92 descriptor set must contain at least one handle to a socket. 93 94 It is unclear why Winsock does not just handle this for us instead of 95 calling this an error. Luckily, with Winsock, we can _also_ ask how 96 many bits are set on an fd_set. So, let's just check it beforehand. 97 */ 98 return select((int)maxfd + 1, 99 fds_read && fds_read->fd_count ? fds_read : NULL, 100 fds_write && fds_write->fd_count ? fds_write : NULL, 101 fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout); 102 #else 103 return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout); 104 #endif 105 } 106 107 #endif 108 109 /* 110 * Wait for read or write events on a set of file descriptors. It uses poll() 111 * when poll() is available, in order to avoid limits with FD_SETSIZE, 112 * otherwise select() is used. An error is returned if select() is being used 113 * and a file descriptor is too large for FD_SETSIZE. 114 * 115 * A negative timeout value makes this function wait indefinitely, unless no 116 * valid file descriptor is given, when this happens the negative timeout is 117 * ignored and the function times out immediately. 118 * 119 * Return values: 120 * -1 = system call error or fd >= FD_SETSIZE 121 * 0 = timeout 122 * [bitmask] = action as described below 123 * 124 * CURL_CSELECT_IN - first socket is readable 125 * CURL_CSELECT_IN2 - second socket is readable 126 * CURL_CSELECT_OUT - write socket is writable 127 * CURL_CSELECT_ERR - an error condition occurred 128 */ 129 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ 130 curl_socket_t readfd1, 131 curl_socket_t writefd, /* socket to write to */ 132 timediff_t timeout_ms) /* milliseconds to wait */ 133 { 134 struct pollfd pfd[3]; 135 int num; 136 int r; 137 138 if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && 139 (writefd == CURL_SOCKET_BAD)) { 140 /* no sockets, just wait */ 141 return curlx_wait_ms(timeout_ms); 142 } 143 144 /* Avoid initial timestamp, avoid curlx_now() call, when elapsed 145 time in this function does not need to be measured. This happens 146 when function is called with a zero timeout or a negative timeout 147 value indicating a blocking call should be performed. */ 148 149 num = 0; 150 if(readfd0 != CURL_SOCKET_BAD) { 151 pfd[num].fd = readfd0; 152 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; 153 pfd[num].revents = 0; 154 num++; 155 } 156 if(readfd1 != CURL_SOCKET_BAD) { 157 pfd[num].fd = readfd1; 158 pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; 159 pfd[num].revents = 0; 160 num++; 161 } 162 if(writefd != CURL_SOCKET_BAD) { 163 pfd[num].fd = writefd; 164 pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI; 165 pfd[num].revents = 0; 166 num++; 167 } 168 169 r = Curl_poll(pfd, (unsigned int)num, timeout_ms); 170 if(r <= 0) 171 return r; 172 173 r = 0; 174 num = 0; 175 if(readfd0 != CURL_SOCKET_BAD) { 176 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) 177 r |= CURL_CSELECT_IN; 178 if(pfd[num].revents & (POLLPRI|POLLNVAL)) 179 r |= CURL_CSELECT_ERR; 180 num++; 181 } 182 if(readfd1 != CURL_SOCKET_BAD) { 183 if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) 184 r |= CURL_CSELECT_IN2; 185 if(pfd[num].revents & (POLLPRI|POLLNVAL)) 186 r |= CURL_CSELECT_ERR; 187 num++; 188 } 189 if(writefd != CURL_SOCKET_BAD) { 190 if(pfd[num].revents & (POLLWRNORM|POLLOUT)) 191 r |= CURL_CSELECT_OUT; 192 if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) 193 r |= CURL_CSELECT_ERR; 194 } 195 196 return r; 197 } 198 199 /* 200 * This is a wrapper around poll(). If poll() does not exist, then 201 * select() is used instead. An error is returned if select() is 202 * being used and a file descriptor is too large for FD_SETSIZE. 203 * A negative timeout value makes this function wait indefinitely, 204 * unless no valid file descriptor is given, when this happens the 205 * negative timeout is ignored and the function times out immediately. 206 * 207 * Return values: 208 * -1 = system call error or fd >= FD_SETSIZE 209 * 0 = timeout 210 * N = number of structures with non zero revent fields 211 */ 212 int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) 213 { 214 #ifdef HAVE_POLL 215 int pending_ms; 216 #else 217 fd_set fds_read; 218 fd_set fds_write; 219 fd_set fds_err; 220 curl_socket_t maxfd; 221 #endif 222 bool fds_none = TRUE; 223 unsigned int i; 224 int r; 225 226 if(ufds) { 227 for(i = 0; i < nfds; i++) { 228 if(ufds[i].fd != CURL_SOCKET_BAD) { 229 fds_none = FALSE; 230 break; 231 } 232 } 233 } 234 if(fds_none) { 235 /* no sockets, just wait */ 236 return curlx_wait_ms(timeout_ms); 237 } 238 239 /* Avoid initial timestamp, avoid curlx_now() call, when elapsed 240 time in this function does not need to be measured. This happens 241 when function is called with a zero timeout or a negative timeout 242 value indicating a blocking call should be performed. */ 243 244 #ifdef HAVE_POLL 245 246 /* prevent overflow, timeout_ms is typecast to int. */ 247 #if TIMEDIFF_T_MAX > INT_MAX 248 if(timeout_ms > INT_MAX) 249 timeout_ms = INT_MAX; 250 #endif 251 if(timeout_ms > 0) 252 pending_ms = (int)timeout_ms; 253 else if(timeout_ms < 0) 254 pending_ms = -1; 255 else 256 pending_ms = 0; 257 r = poll(ufds, nfds, pending_ms); 258 if(r <= 0) { 259 if((r == -1) && (SOCKERRNO == SOCKEINTR)) 260 /* make EINTR from select or poll not a "lethal" error */ 261 r = 0; 262 return r; 263 } 264 265 for(i = 0; i < nfds; i++) { 266 if(ufds[i].fd == CURL_SOCKET_BAD) 267 continue; 268 if(ufds[i].revents & POLLHUP) 269 ufds[i].revents |= POLLIN; 270 if(ufds[i].revents & POLLERR) 271 ufds[i].revents |= POLLIN|POLLOUT; 272 } 273 274 #else /* HAVE_POLL */ 275 276 FD_ZERO(&fds_read); 277 FD_ZERO(&fds_write); 278 FD_ZERO(&fds_err); 279 maxfd = (curl_socket_t)-1; 280 281 for(i = 0; i < nfds; i++) { 282 ufds[i].revents = 0; 283 if(ufds[i].fd == CURL_SOCKET_BAD) 284 continue; 285 VERIFY_SOCK(ufds[i].fd); 286 if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| 287 POLLRDNORM|POLLWRNORM|POLLRDBAND)) { 288 if(ufds[i].fd > maxfd) 289 maxfd = ufds[i].fd; 290 if(ufds[i].events & (POLLRDNORM|POLLIN)) 291 FD_SET(ufds[i].fd, &fds_read); 292 if(ufds[i].events & (POLLWRNORM|POLLOUT)) 293 FD_SET(ufds[i].fd, &fds_write); 294 if(ufds[i].events & (POLLRDBAND|POLLPRI)) 295 FD_SET(ufds[i].fd, &fds_err); 296 } 297 } 298 299 /* 300 Note also that Winsock ignores the first argument, so we do not worry 301 about the fact that maxfd is computed incorrectly with Winsock (since 302 curl_socket_t is unsigned in such cases and thus -1 is the largest 303 value). 304 */ 305 r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); 306 if(r <= 0) { 307 if((r == -1) && (SOCKERRNO == SOCKEINTR)) 308 /* make EINTR from select or poll not a "lethal" error */ 309 r = 0; 310 return r; 311 } 312 313 r = 0; 314 for(i = 0; i < nfds; i++) { 315 ufds[i].revents = 0; 316 if(ufds[i].fd == CURL_SOCKET_BAD) 317 continue; 318 if(FD_ISSET(ufds[i].fd, &fds_read)) { 319 if(ufds[i].events & POLLRDNORM) 320 ufds[i].revents |= POLLRDNORM; 321 if(ufds[i].events & POLLIN) 322 ufds[i].revents |= POLLIN; 323 } 324 if(FD_ISSET(ufds[i].fd, &fds_write)) { 325 if(ufds[i].events & POLLWRNORM) 326 ufds[i].revents |= POLLWRNORM; 327 if(ufds[i].events & POLLOUT) 328 ufds[i].revents |= POLLOUT; 329 } 330 if(FD_ISSET(ufds[i].fd, &fds_err)) { 331 if(ufds[i].events & POLLRDBAND) 332 ufds[i].revents |= POLLRDBAND; 333 if(ufds[i].events & POLLPRI) 334 ufds[i].revents |= POLLPRI; 335 } 336 if(ufds[i].revents) 337 r++; 338 } 339 340 #endif /* HAVE_POLL */ 341 342 return r; 343 } 344 345 void Curl_pollfds_init(struct curl_pollfds *cpfds, 346 struct pollfd *static_pfds, 347 unsigned int static_count) 348 { 349 DEBUGASSERT(cpfds); 350 memset(cpfds, 0, sizeof(*cpfds)); 351 if(static_pfds && static_count) { 352 cpfds->pfds = static_pfds; 353 cpfds->count = static_count; 354 } 355 } 356 357 void Curl_pollfds_reset(struct curl_pollfds *cpfds) 358 { 359 cpfds->n = 0; 360 } 361 362 void Curl_pollfds_cleanup(struct curl_pollfds *cpfds) 363 { 364 DEBUGASSERT(cpfds); 365 if(cpfds->allocated_pfds) { 366 free(cpfds->pfds); 367 } 368 memset(cpfds, 0, sizeof(*cpfds)); 369 } 370 371 static CURLcode cpfds_increase(struct curl_pollfds *cpfds, unsigned int inc) 372 { 373 struct pollfd *new_fds; 374 unsigned int new_count = cpfds->count + inc; 375 376 new_fds = calloc(new_count, sizeof(struct pollfd)); 377 if(!new_fds) 378 return CURLE_OUT_OF_MEMORY; 379 380 memcpy(new_fds, cpfds->pfds, cpfds->count * sizeof(struct pollfd)); 381 if(cpfds->allocated_pfds) 382 free(cpfds->pfds); 383 cpfds->pfds = new_fds; 384 cpfds->count = new_count; 385 cpfds->allocated_pfds = TRUE; 386 return CURLE_OK; 387 } 388 389 static CURLcode cpfds_add_sock(struct curl_pollfds *cpfds, 390 curl_socket_t sock, short events, bool fold) 391 { 392 int i; 393 394 if(fold && cpfds->n <= INT_MAX) { 395 for(i = (int)cpfds->n - 1; i >= 0; --i) { 396 if(sock == cpfds->pfds[i].fd) { 397 cpfds->pfds[i].events |= events; 398 return CURLE_OK; 399 } 400 } 401 } 402 /* not folded, add new entry */ 403 if(cpfds->n >= cpfds->count) { 404 if(cpfds_increase(cpfds, 100)) 405 return CURLE_OUT_OF_MEMORY; 406 } 407 cpfds->pfds[cpfds->n].fd = sock; 408 cpfds->pfds[cpfds->n].events = events; 409 ++cpfds->n; 410 return CURLE_OK; 411 } 412 413 CURLcode Curl_pollfds_add_sock(struct curl_pollfds *cpfds, 414 curl_socket_t sock, short events) 415 { 416 return cpfds_add_sock(cpfds, sock, events, FALSE); 417 } 418 419 CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds, 420 struct easy_pollset *ps) 421 { 422 size_t i; 423 424 DEBUGASSERT(cpfds); 425 DEBUGASSERT(ps); 426 for(i = 0; i < ps->num; i++) { 427 short events = 0; 428 if(ps->actions[i] & CURL_POLL_IN) 429 events |= POLLIN; 430 if(ps->actions[i] & CURL_POLL_OUT) 431 events |= POLLOUT; 432 if(events) { 433 if(cpfds_add_sock(cpfds, ps->sockets[i], events, TRUE)) 434 return CURLE_OUT_OF_MEMORY; 435 } 436 } 437 return CURLE_OK; 438 } 439 440 void Curl_waitfds_init(struct Curl_waitfds *cwfds, 441 struct curl_waitfd *static_wfds, 442 unsigned int static_count) 443 { 444 DEBUGASSERT(cwfds); 445 DEBUGASSERT(static_wfds || !static_count); 446 memset(cwfds, 0, sizeof(*cwfds)); 447 cwfds->wfds = static_wfds; 448 cwfds->count = static_count; 449 } 450 451 static unsigned int cwfds_add_sock(struct Curl_waitfds *cwfds, 452 curl_socket_t sock, short events) 453 { 454 int i; 455 if(!cwfds->wfds) { 456 DEBUGASSERT(!cwfds->count && !cwfds->n); 457 return 1; 458 } 459 if(cwfds->n <= INT_MAX) { 460 for(i = (int)cwfds->n - 1; i >= 0; --i) { 461 if(sock == cwfds->wfds[i].fd) { 462 cwfds->wfds[i].events |= events; 463 return 0; 464 } 465 } 466 } 467 /* not folded, add new entry */ 468 if(cwfds->n < cwfds->count) { 469 cwfds->wfds[cwfds->n].fd = sock; 470 cwfds->wfds[cwfds->n].events = events; 471 ++cwfds->n; 472 } 473 return 1; 474 } 475 476 unsigned int Curl_waitfds_add_ps(struct Curl_waitfds *cwfds, 477 struct easy_pollset *ps) 478 { 479 size_t i; 480 unsigned int need = 0; 481 482 DEBUGASSERT(cwfds); 483 DEBUGASSERT(ps); 484 for(i = 0; i < ps->num; i++) { 485 short events = 0; 486 if(ps->actions[i] & CURL_POLL_IN) 487 events |= CURL_WAIT_POLLIN; 488 if(ps->actions[i] & CURL_POLL_OUT) 489 events |= CURL_WAIT_POLLOUT; 490 if(events) 491 need += cwfds_add_sock(cwfds, ps->sockets[i], events); 492 } 493 return need; 494 }