mirror of
https://github.com/moparisthebest/curl
synced 2025-01-10 21:48:10 -05:00
global_init: assume the EINTR bit by default
- Removed from global_init since it isn't thread-safe. The symbol will still remain to not break compiles, it just won't have any effect going forward. - make the internals NOT loop on EINTR (the opposite from previously). It only risks returning from the select/poll/wait functions early, and that should be risk-free. Closes #4840
This commit is contained in:
parent
34e6bc42b0
commit
1ad49feb71
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@ -87,9 +87,11 @@ Initialise nothing extra. This sets no bit.
|
||||
A sensible default. It will init both SSL and Win32. Right now, this equals
|
||||
the functionality of the \fBCURL_GLOBAL_ALL\fP mask.
|
||||
.IP CURL_GLOBAL_ACK_EINTR
|
||||
When this flag is set, curl will acknowledge EINTR condition when connecting
|
||||
or when waiting for data. Otherwise, curl waits until full timeout
|
||||
elapses. (Added in 7.30.0)
|
||||
This bit has no point since 7.69.0 but its behavior is instead the default.
|
||||
|
||||
Before 7.69.0: when this flag is set, curl will acknowledge EINTR condition
|
||||
when connecting or when waiting for data. Otherwise, curl waits until full
|
||||
timeout elapses. (Added in 7.30.0)
|
||||
.SH RETURN VALUE
|
||||
If this function returns non-zero, something went wrong and you cannot use the
|
||||
other curl functions.
|
||||
|
@ -193,8 +193,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(flags & CURL_GLOBAL_ACK_EINTR)
|
||||
Curl_ack_eintr = 1;
|
||||
#ifdef USE_WOLFSSH
|
||||
if(WS_SUCCESS != wolfSSH_Init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
init_flags = flags;
|
||||
|
||||
|
215
lib/select.c
215
lib/select.c
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -53,9 +53,6 @@
|
||||
/* Convenience local macros */
|
||||
#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv)
|
||||
|
||||
int Curl_ack_eintr = 0;
|
||||
#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
|
||||
|
||||
/*
|
||||
* Internal function used for waiting a specific amount of ms
|
||||
* in Curl_socket_check() and Curl_poll() when no file descriptor
|
||||
@ -74,13 +71,6 @@ int Curl_ack_eintr = 0;
|
||||
*/
|
||||
int Curl_wait_ms(int timeout_ms)
|
||||
{
|
||||
#if !defined(MSDOS) && !defined(USE_WINSOCK)
|
||||
#ifndef HAVE_POLL_FINE
|
||||
struct timeval pending_tv;
|
||||
#endif
|
||||
struct curltime initial_tv;
|
||||
int pending_ms;
|
||||
#endif
|
||||
int r = 0;
|
||||
|
||||
if(!timeout_ms)
|
||||
@ -94,28 +84,16 @@ int Curl_wait_ms(int timeout_ms)
|
||||
#elif defined(USE_WINSOCK)
|
||||
Sleep(timeout_ms);
|
||||
#else
|
||||
pending_ms = timeout_ms;
|
||||
initial_tv = Curl_now();
|
||||
do {
|
||||
int error;
|
||||
#if defined(HAVE_POLL_FINE)
|
||||
r = poll(NULL, 0, pending_ms);
|
||||
r = poll(NULL, 0, timeout_ms);
|
||||
#else
|
||||
pending_tv.tv_sec = pending_ms / 1000;
|
||||
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
|
||||
{
|
||||
struct timeval pending_tv;
|
||||
pending_tv.tv_sec = timeout_ms / 1000;
|
||||
pending_tv.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
r = select(0, NULL, NULL, NULL, &pending_tv);
|
||||
}
|
||||
#endif /* HAVE_POLL_FINE */
|
||||
if(r != -1)
|
||||
break;
|
||||
error = SOCKERRNO;
|
||||
if(error && ERROR_NOT_EINTR(error))
|
||||
break;
|
||||
pending_ms = timeout_ms - ELAPSED_MS();
|
||||
if(pending_ms <= 0) {
|
||||
r = 0; /* Simulate a "call timed out" case */
|
||||
break;
|
||||
}
|
||||
} while(r == -1);
|
||||
#endif /* USE_WINSOCK */
|
||||
if(r)
|
||||
r = -1;
|
||||
@ -158,7 +136,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
|
||||
fd_set fds_err;
|
||||
curl_socket_t maxfd;
|
||||
#endif
|
||||
struct curltime initial_tv = {0, 0};
|
||||
int pending_ms = 0;
|
||||
int r;
|
||||
int ret;
|
||||
@ -183,7 +160,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
|
||||
|
||||
if(timeout_ms > 0) {
|
||||
pending_ms = (int)timeout_ms;
|
||||
initial_tv = Curl_now();
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_FINE
|
||||
@ -208,26 +184,11 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
|
||||
num++;
|
||||
}
|
||||
|
||||
do {
|
||||
int error;
|
||||
if(timeout_ms < 0)
|
||||
pending_ms = -1;
|
||||
else if(!timeout_ms)
|
||||
pending_ms = 0;
|
||||
r = poll(pfd, num, pending_ms);
|
||||
if(r != -1)
|
||||
break;
|
||||
error = SOCKERRNO;
|
||||
if(error && ERROR_NOT_EINTR(error))
|
||||
break;
|
||||
if(timeout_ms > 0) {
|
||||
pending_ms = (int)(timeout_ms - ELAPSED_MS());
|
||||
if(pending_ms <= 0) {
|
||||
r = 0; /* Simulate a "call timed out" case */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(r == -1);
|
||||
if(timeout_ms < 0)
|
||||
pending_ms = -1;
|
||||
else if(!timeout_ms)
|
||||
pending_ms = 0;
|
||||
r = poll(pfd, num, pending_ms);
|
||||
|
||||
if(r < 0)
|
||||
return -1;
|
||||
@ -290,61 +251,45 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
|
||||
|
||||
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
|
||||
|
||||
do {
|
||||
int error;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* WinSock select() must not be called with an fd_set that contains zero
|
||||
fd flags, or it will return WSAEINVAL. But, it also can't be called
|
||||
with no fd_sets at all! From the documentation:
|
||||
/* WinSock select() must not be called with an fd_set that contains zero
|
||||
fd flags, or it will return WSAEINVAL. But, it also can't be called
|
||||
with no fd_sets at all! From the documentation:
|
||||
|
||||
Any two of the parameters, readfds, writefds, or exceptfds, can be
|
||||
given as null. At least one must be non-null, and any non-null
|
||||
descriptor set must contain at least one handle to a socket.
|
||||
Any two of the parameters, readfds, writefds, or exceptfds, can be
|
||||
given as null. At least one must be non-null, and any non-null
|
||||
descriptor set must contain at least one handle to a socket.
|
||||
|
||||
We know that we have at least one bit set in at least two fd_sets in
|
||||
this case, but we may have no bits set in either fds_read or fd_write,
|
||||
so check for that and handle it. Luckily, with WinSock, we can _also_
|
||||
ask how many bits are set on an fd_set.
|
||||
We know that we have at least one bit set in at least two fd_sets in
|
||||
this case, but we may have no bits set in either fds_read or fd_write,
|
||||
so check for that and handle it. Luckily, with WinSock, we can _also_
|
||||
ask how many bits are set on an fd_set.
|
||||
|
||||
It is unclear why WinSock doesn't just handle this for us instead of
|
||||
calling this an error.
|
||||
It is unclear why WinSock doesn't just handle this for us instead of
|
||||
calling this an error.
|
||||
|
||||
Note also that WinSock ignores the first argument, so we don't worry
|
||||
about the fact that maxfd is computed incorrectly with WinSock (since
|
||||
curl_socket_t is unsigned in such cases and thus -1 is the largest
|
||||
value).
|
||||
*/
|
||||
Note also that WinSock ignores the first argument, so we don't worry
|
||||
about the fact that maxfd is computed incorrectly with WinSock (since
|
||||
curl_socket_t is unsigned in such cases and thus -1 is the largest
|
||||
value).
|
||||
*/
|
||||
#ifdef USE_WINSOCK
|
||||
r = select((int)maxfd + 1,
|
||||
fds_read.fd_count ? &fds_read : NULL,
|
||||
fds_write.fd_count ? &fds_write : NULL,
|
||||
&fds_err, ptimeout);
|
||||
r = select((int)maxfd + 1,
|
||||
fds_read.fd_count ? &fds_read : NULL,
|
||||
fds_write.fd_count ? &fds_write : NULL,
|
||||
&fds_err, ptimeout);
|
||||
#else
|
||||
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
|
||||
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
|
||||
#endif
|
||||
|
||||
if(r != -1)
|
||||
break;
|
||||
error = SOCKERRNO;
|
||||
if(error && ERROR_NOT_EINTR(error))
|
||||
break;
|
||||
if(timeout_ms > 0) {
|
||||
pending_ms = (int)(timeout_ms - ELAPSED_MS());
|
||||
if(pending_ms <= 0) {
|
||||
r = 0; /* Simulate a "call timed out" case */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(r == -1);
|
||||
|
||||
if(r < 0)
|
||||
return -1;
|
||||
if(r == 0)
|
||||
@ -399,7 +344,6 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
|
||||
fd_set fds_err;
|
||||
curl_socket_t maxfd;
|
||||
#endif
|
||||
struct curltime initial_tv = {0, 0};
|
||||
bool fds_none = TRUE;
|
||||
unsigned int i;
|
||||
int pending_ms = 0;
|
||||
@ -425,31 +369,15 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
|
||||
|
||||
if(timeout_ms > 0) {
|
||||
pending_ms = timeout_ms;
|
||||
initial_tv = Curl_now();
|
||||
}
|
||||
|
||||
#ifdef HAVE_POLL_FINE
|
||||
|
||||
do {
|
||||
int error;
|
||||
if(timeout_ms < 0)
|
||||
pending_ms = -1;
|
||||
else if(!timeout_ms)
|
||||
pending_ms = 0;
|
||||
r = poll(ufds, nfds, pending_ms);
|
||||
if(r != -1)
|
||||
break;
|
||||
error = SOCKERRNO;
|
||||
if(error && ERROR_NOT_EINTR(error))
|
||||
break;
|
||||
if(timeout_ms > 0) {
|
||||
pending_ms = (int)(timeout_ms - ELAPSED_MS());
|
||||
if(pending_ms <= 0) {
|
||||
r = 0; /* Simulate a "call timed out" case */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(r == -1);
|
||||
if(timeout_ms < 0)
|
||||
pending_ms = -1;
|
||||
else if(!timeout_ms)
|
||||
pending_ms = 0;
|
||||
r = poll(ufds, nfds, pending_ms);
|
||||
|
||||
if(r < 0)
|
||||
return -1;
|
||||
@ -502,42 +430,27 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
|
||||
|
||||
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
|
||||
|
||||
do {
|
||||
int error;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
r = select((int)maxfd + 1,
|
||||
/* WinSock select() can't handle fd_sets with zero bits set, so
|
||||
don't give it such arguments. See the comment about this in
|
||||
Curl_check_socket().
|
||||
*/
|
||||
fds_read.fd_count ? &fds_read : NULL,
|
||||
fds_write.fd_count ? &fds_write : NULL,
|
||||
fds_err.fd_count ? &fds_err : NULL, ptimeout);
|
||||
r = select((int)maxfd + 1,
|
||||
/* WinSock select() can't handle fd_sets with zero bits set, so
|
||||
don't give it such arguments. See the comment about this in
|
||||
Curl_check_socket().
|
||||
*/
|
||||
fds_read.fd_count ? &fds_read : NULL,
|
||||
fds_write.fd_count ? &fds_write : NULL,
|
||||
fds_err.fd_count ? &fds_err : NULL, ptimeout);
|
||||
#else
|
||||
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
|
||||
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
|
||||
#endif
|
||||
if(r != -1)
|
||||
break;
|
||||
error = SOCKERRNO;
|
||||
if(error && ERROR_NOT_EINTR(error))
|
||||
break;
|
||||
if(timeout_ms > 0) {
|
||||
pending_ms = timeout_ms - ELAPSED_MS();
|
||||
if(pending_ms <= 0) {
|
||||
r = 0; /* Simulate a "call timed out" case */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(r == -1);
|
||||
|
||||
if(r < 0)
|
||||
return -1;
|
||||
|
10
lib/select.h
10
lib/select.h
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -75,20 +75,12 @@ struct pollfd
|
||||
int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
|
||||
curl_socket_t writefd,
|
||||
time_t timeout_ms);
|
||||
|
||||
#define SOCKET_READABLE(x,z) \
|
||||
Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, (time_t)z)
|
||||
#define SOCKET_WRITABLE(x,z) \
|
||||
Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, (time_t)z)
|
||||
|
||||
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
|
||||
|
||||
/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set,
|
||||
* EINTR condition is honored and function might exit early without
|
||||
* awaiting full timeout. Otherwise EINTR will be ignored and full
|
||||
* timeout will elapse. */
|
||||
extern int Curl_ack_eintr;
|
||||
|
||||
int Curl_wait_ms(int timeout_ms);
|
||||
|
||||
#ifdef TPF
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
Loading…
Reference in New Issue
Block a user