New Internal wrapper function Curl_select() around select (2), it
uses poll() when a fine poll() is available, so now libcurl can be built without select() support at all if a fine poll() is available.
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -9,6 +9,10 @@
|
||||
Yang Tse (27 March 2007)
|
||||
- Internal function Curl_select() renamed to Curl_socket_ready()
|
||||
|
||||
New Internal wrapper function Curl_select() around select (2), it
|
||||
uses poll() when a fine poll() is available, so now libcurl can be
|
||||
built without select() support at all if a fine poll() is available.
|
||||
|
||||
Daniel S (25 March 2007)
|
||||
- Daniel Johnson fixed multi code to traverse the easy handle list properly.
|
||||
A left-over bug from the February 21 fix.
|
||||
|
||||
@@ -24,6 +24,7 @@ This release includes the following changes:
|
||||
o added experimental CURL_ACKNOWLEDGE_EINTR symbol definition check
|
||||
o --key and new --pubkey options for SSH public key file logins
|
||||
o --pass now works for a SSH public key file, too
|
||||
o select (2) support no longer needed to build the library if poll() used
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
|
||||
@@ -61,10 +61,6 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#endif /* WIN32 ... */
|
||||
|
||||
#include "urldata.h"
|
||||
@@ -79,6 +75,7 @@
|
||||
#include "memory.h"
|
||||
#include "progress.h"
|
||||
#include "easyif.h"
|
||||
#include "select.h"
|
||||
#include "sendf.h" /* for failf function prototype */
|
||||
#include <ca-bundle.h>
|
||||
|
||||
@@ -417,7 +414,7 @@ CURLcode curl_easy_perform(CURL *easy)
|
||||
/* get file descriptors from the transfers */
|
||||
curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
|
||||
|
||||
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||
rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
|
||||
|
||||
if(rc == -1)
|
||||
/* select error */
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include "url.h"
|
||||
#include "multiif.h"
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -144,8 +145,8 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
|
||||
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
|
||||
|
||||
(void)select(nfds, &read_fds, &write_fds, NULL,
|
||||
(struct timeval *)&tv);
|
||||
(void)Curl_select(nfds, &read_fds, &write_fds, NULL,
|
||||
(struct timeval *)&tv);
|
||||
|
||||
/* Call ares_process() unconditonally here, even if we simply timed out
|
||||
above, as otherwise the ares name resolve won't timeout! */
|
||||
@@ -210,7 +211,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||
/* no file descriptors means we're done waiting */
|
||||
break;
|
||||
tvp = ares_timeout(data->state.areschannel, &store, &tv);
|
||||
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
|
||||
count = Curl_select(nfds, &read_fds, &write_fds, NULL, tvp);
|
||||
if ((count < 0) && (SOCKERRNO != EINVAL))
|
||||
break;
|
||||
|
||||
|
||||
197
lib/select.c
197
lib/select.c
@@ -32,8 +32,8 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SELECT
|
||||
#error "We can't compile without select() support!"
|
||||
#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
|
||||
#error "We can't compile without select() or poll() support."
|
||||
#endif
|
||||
|
||||
#ifdef __BEOS__
|
||||
@@ -64,6 +64,7 @@
|
||||
|
||||
#if defined(USE_WINSOCK) || defined(TPF)
|
||||
#define VERIFY_SOCK(x) do { } while (0)
|
||||
#define VERIFY_NFDS(x) do { } while (0)
|
||||
#else
|
||||
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
|
||||
#define VERIFY_SOCK(x) do { \
|
||||
@@ -72,6 +73,13 @@
|
||||
return -1; \
|
||||
} \
|
||||
} while(0)
|
||||
#define VALID_NFDS(n) (((n) >= 0) && ((n) <= FD_SETSIZE))
|
||||
#define VERIFY_NFDS(x) do { \
|
||||
if(!VALID_NFDS(x)) { \
|
||||
SET_SOCKERRNO(EINVAL); \
|
||||
return -1; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* Convenience local macros */
|
||||
@@ -84,6 +92,8 @@
|
||||
#define error_not_EINTR (1)
|
||||
#endif
|
||||
|
||||
#define SMALL_POLLNFDS 0X20
|
||||
|
||||
/*
|
||||
* Internal function used for waiting a specific amount of ms
|
||||
* in Curl_socket_ready() and Curl_poll() when no file descriptor
|
||||
@@ -424,6 +434,189 @@ 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;
|
||||
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 = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
|
||||
}
|
||||
else {
|
||||
timeout_ms = -1;
|
||||
}
|
||||
|
||||
if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) {
|
||||
r = wait_ms(timeout_ms);
|
||||
return r;
|
||||
}
|
||||
|
||||
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 = calloc((size_t)poll_nfds, sizeof(struct pollfd));
|
||||
if (!poll_fds) {
|
||||
SET_SOCKERRNO(ENOBUFS);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (poll_fds) {
|
||||
ix = 0;
|
||||
fd = nfds;
|
||||
while (fd--) {
|
||||
poll_fds[ix].events = 0;
|
||||
if (fds_read && (0 != FD_ISSET(fd, fds_read)))
|
||||
poll_fds[ix].events |= (POLLRDNORM|POLLIN);
|
||||
if (fds_write && (0 != FD_ISSET(fd, fds_write)))
|
||||
poll_fds[ix].events |= (POLLWRNORM|POLLOUT);
|
||||
if (fds_excep && (0 != FD_ISSET(fd, fds_excep)))
|
||||
poll_fds[ix].events |= (POLLRDBAND|POLLPRI);
|
||||
if (poll_fds[ix].events) {
|
||||
poll_fds[ix].fd = fd;
|
||||
poll_fds[ix].revents = 0;
|
||||
ix++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if (timeout_ms < 0)
|
||||
pending_ms = -1;
|
||||
r = poll(poll_fds, poll_nfds, pending_ms);
|
||||
} while ((r == -1) && (error = SOCKERRNO) &&
|
||||
(error != EINVAL) && error_not_EINTR &&
|
||||
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
|
||||
|
||||
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 (ptimeout) {
|
||||
pending_tv.tv_sec = pending_ms / 1000;
|
||||
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
|
||||
}
|
||||
r = select(nfds, fds_read, fds_write, fds_excep, ptimeout);
|
||||
} while ((r == -1) && (error = SOCKERRNO) &&
|
||||
(error != EINVAL) && (error != EBADF) && error_not_EINTR &&
|
||||
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
|
||||
|
||||
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.
|
||||
|
||||
16
lib/select.h
16
lib/select.h
@@ -64,6 +64,18 @@ struct pollfd
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef POLLRDNORM
|
||||
#define POLLRDNORM POLLIN
|
||||
#endif
|
||||
|
||||
#ifndef POLLWRNORM
|
||||
#define POLLWRNORM POLLOUT
|
||||
#endif
|
||||
|
||||
#ifndef POLLRDBAND
|
||||
#define POLLRDBAND POLLPRI
|
||||
#endif
|
||||
|
||||
#define CSELECT_IN 0x01
|
||||
#define CSELECT_OUT 0x02
|
||||
#define CSELECT_ERR 0x04
|
||||
@@ -72,6 +84,10 @@ int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_m
|
||||
|
||||
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
|
||||
|
||||
int Curl_select(int nfds,
|
||||
fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep,
|
||||
struct timeval *timeout);
|
||||
|
||||
#ifdef TPF
|
||||
int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
|
||||
fd_set* excepts, struct timeval* tv);
|
||||
|
||||
Reference in New Issue
Block a user