From 4c663ba9a8fbb9d58369e613230693b487b18d39 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 31 May 2007 11:34:32 +0000 Subject: When transferring 500 downloads in parallel with a c-ares enabled build only to find that it crashed miserably, and this was due to some select()isms left in the code. This was due to API restrictions in c-ares 1.3.x, but with the upcoming c-ares 1.4.0 this is no longer the case so now libcurl runs much better with c-ares and the multi interface with > 1024 file descriptors in use. --- lib/select.c | 221 ----------------------------------------------------------- 1 file changed, 221 deletions(-) (limited to 'lib/select.c') diff --git a/lib/select.c b/lib/select.c index daa591eae..28bb141b1 100644 --- a/lib/select.c +++ b/lib/select.c @@ -482,227 +482,6 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) return r; } -/* - * This is a wrapper around select(). 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 the number of file descriptors is larger than - * FD_SETSIZE. A NULL timeout pointer makes this function wait - * indefinitely, unles no valid file descriptor is given, when this - * happens the NULL 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 nfds > FD_SETSIZE - * 0 = timeout - * N = number of file descriptors kept in file descriptor sets. - */ -int Curl_select(int nfds, - fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep, - struct timeval *timeout) -{ - struct timeval initial_tv; - int timeout_ms; - int pending_ms = 0; - int error; - int r; -#ifdef HAVE_POLL_FINE - struct pollfd small_fds[SMALL_POLLNFDS]; - struct pollfd *poll_fds; - int ix; - int fd; - int poll_nfds = 0; -#else - struct timeval pending_tv; - struct timeval *ptimeout; -#endif - int ret = 0; - - if ((nfds < 0) || - ((nfds > 0) && (!fds_read && !fds_write && !fds_excep))) { - SET_SOCKERRNO(EINVAL); - return -1; - } - - if (timeout) { - if ((timeout->tv_sec < 0) || - (timeout->tv_usec < 0) || - (timeout->tv_usec >= 1000000)) { - SET_SOCKERRNO(EINVAL); - return -1; - } - timeout_ms = (int)(timeout->tv_sec * 1000) + - (int)(timeout->tv_usec / 1000); - } - else { - timeout_ms = -1; - } - - if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) { - r = wait_ms(timeout_ms); - return r; - } - - /* Avoid initial timestamp, avoid gettimeofday() call, when elapsed - time in this function does not need to be measured. This happens - when function is called with a zero timeout in the timeval struct - referenced argument or when a NULL pointer is received as timeval - reference indicating a blocking call should be performed. */ - - if (timeout_ms > 0) { - pending_ms = timeout_ms; - initial_tv = curlx_tvnow(); - } - -#ifdef HAVE_POLL_FINE - - if (fds_read || fds_write || fds_excep) { - fd = nfds; - while (fd--) { - if ((fds_read && (0 != FD_ISSET(fd, fds_read))) || - (fds_write && (0 != FD_ISSET(fd, fds_write))) || - (fds_excep && (0 != FD_ISSET(fd, fds_excep)))) - poll_nfds++; - } - } - - if (!poll_nfds) - poll_fds = NULL; - else if (poll_nfds <= SMALL_POLLNFDS) - poll_fds = small_fds; - else { - poll_fds = malloc(poll_nfds * sizeof(struct pollfd)); - if (!poll_fds) { - SET_SOCKERRNO(ENOBUFS); - return -1; - } - } - - if (poll_fds) { - int events; - ix = 0; - fd = nfds; - while (fd--) { - events = 0; - if (fds_read && (0 != FD_ISSET(fd, fds_read))) - events |= (POLLRDNORM|POLLIN); - if (fds_write && (0 != FD_ISSET(fd, fds_write))) - events |= (POLLWRNORM|POLLOUT); - if (fds_excep && (0 != FD_ISSET(fd, fds_excep))) - events |= (POLLRDBAND|POLLPRI); - if (events) { - poll_fds[ix].events = events; - poll_fds[ix].fd = fd; - poll_fds[ix].revents = 0; - ix++; - if(ix == poll_nfds) - /* since we know this is the total amount of descriptors with - interesting actions, we can skip the rest of the loop at this - point */ - break; - } - } - } - - do { - if (timeout_ms < 0) - pending_ms = -1; - else if (!timeout_ms) - pending_ms = 0; - r = poll(poll_fds, poll_nfds, pending_ms); - if (r != -1) - break; - error = SOCKERRNO; - if ((error == EINVAL) || error_is_EINTR) - break; - if (timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if (pending_ms <= 0) - break; - } - } while (r == -1); - - if (r < 0) - ret = -1; - - if (r > 0) { - ix = poll_nfds; - while (ix--) { - if (poll_fds[ix].revents & POLLNVAL) { - SET_SOCKERRNO(EBADF); - ret = -1; - break; - } - } - } - - if (!ret) { - ix = poll_nfds; - while (ix--) { - if (fds_read && (0 != FD_ISSET(poll_fds[ix].fd, fds_read))) { - if (0 == (poll_fds[ix].revents & (POLLRDNORM|POLLERR|POLLHUP|POLLIN))) - FD_CLR(poll_fds[ix].fd, fds_read); - else - ret++; - } - if (fds_write && (0 != FD_ISSET(poll_fds[ix].fd, fds_write))) { - if (0 == (poll_fds[ix].revents & (POLLWRNORM|POLLERR|POLLHUP|POLLOUT))) - FD_CLR(poll_fds[ix].fd, fds_write); - else - ret++; - } - if (fds_excep && (0 != FD_ISSET(poll_fds[ix].fd, fds_excep))) { - if (0 == (poll_fds[ix].revents & (POLLRDBAND|POLLERR|POLLHUP|POLLPRI))) - FD_CLR(poll_fds[ix].fd, fds_excep); - else - ret++; - } - } - } - - if (poll_fds && (poll_nfds > SMALL_POLLNFDS)) - free(poll_fds); - -#else /* HAVE_POLL_FINE */ - - VERIFY_NFDS(nfds); - - ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; - - do { - if (timeout_ms > 0) { - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; - } - else if (!timeout_ms) { - pending_tv.tv_sec = 0; - pending_tv.tv_usec = 0; - } - r = select(nfds, fds_read, fds_write, fds_excep, ptimeout); - if (r != -1) - break; - error = SOCKERRNO; - if ((error == EINVAL) || (error == EBADF) || error_is_EINTR) - break; - if (timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if (pending_ms <= 0) - break; - } - } while (r == -1); - - if (r < 0) - ret = -1; - else - ret = r; - -#endif /* HAVE_POLL_FINE */ - - return ret; -} - #ifdef TPF /* * This is a replacement for select() on the TPF platform. -- cgit v1.2.3