diff --git a/docs/libcurl/libcurl-errors.3 b/docs/libcurl/libcurl-errors.3 index 9ad29e8c828e09..8ca043cb9779e6 100644 --- a/docs/libcurl/libcurl-errors.3 +++ b/docs/libcurl/libcurl-errors.3 @@ -265,6 +265,8 @@ QUIC connection error. This error may be caused by an SSL library error. QUIC is the protocol used for HTTP/3 transfers. .IP "CURLE_SSL_CLIENTCERT (98)" SSL Client Certificate required. +.IP "CURLE_UNRECOVERABLE_POLL (99)" +An internal call to poll() or select() returned error that is not recoverable. .IP "CURLE_OBSOLETE*" These error codes will never be returned. They were used in an old libcurl version and are currently unused. @@ -309,6 +311,8 @@ Wakeup is unavailable or failed. A function was called with a bad parameter. .IP "CURLM_ABORTED_BY_CALLBACK (11)" A multi handle callback returned error. +.IP "CURLM_UNRECOVERABLE_POLL (12)" +An internal call to poll() or select() returned error that is not recoverable. .SH "CURLSHcode" The "share" interface will return a CURLSHcode to indicate when an error has occurred. Also consider \fIcurl_share_strerror(3)\fP. diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index d8de1607c54c97..2368255d4ff500 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -320,6 +320,7 @@ CURLE_TFTP_UNKNOWNID 7.15.0 CURLE_TOO_MANY_REDIRECTS 7.5 CURLE_UNKNOWN_OPTION 7.21.5 CURLE_UNKNOWN_TELNET_OPTION 7.7 7.21.5 +CURLE_UNRECOVERABLE_POLL 7.84.0 CURLE_UNSUPPORTED_PROTOCOL 7.1 CURLE_UPLOAD_FAILED 7.16.3 CURLE_URL_MALFORMAT 7.1 @@ -523,6 +524,7 @@ CURLM_OK 7.9.6 CURLM_OUT_OF_MEMORY 7.9.6 CURLM_RECURSIVE_API_CALL 7.59.0 CURLM_UNKNOWN_OPTION 7.15.4 +CURLM_UNRECOVERABLE_POLL 7.84.0 CURLM_WAKEUP_FAILURE 7.68.0 CURLMIMEOPT_FORMESCAPE 7.81.0 CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 diff --git a/include/curl/curl.h b/include/curl/curl.h index 13f01a01785e68..49595a26160d98 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -613,6 +613,7 @@ typedef enum { CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ CURLE_PROXY, /* 97 - proxy handshake error */ CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */ + CURLE_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */ CURL_LAST /* never use! */ } CURLcode; diff --git a/include/curl/multi.h b/include/curl/multi.h index 91cd95d32304f7..362eabc7ff5fb4 100644 --- a/include/curl/multi.h +++ b/include/curl/multi.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, , 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,6 +75,7 @@ typedef enum { CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ CURLM_ABORTED_BY_CALLBACK, + CURLM_UNRECOVERABLE_POLL, CURLM_LAST } CURLMcode; diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index c885adef54ca8a..573b4fe042dd81 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -306,7 +306,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, * 2) wait for the timeout period to check for action on ares' sockets. * 3) tell ares to act on all the sockets marked as "with action" * - * return number of sockets it worked on + * return number of sockets it worked on, or -1 on error */ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) @@ -338,8 +338,11 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms) break; } - if(num) + if(num) { nfds = Curl_poll(pfd, num, timeout_ms); + if(nfds < 0) + return -1; + } else nfds = 0; @@ -376,7 +379,8 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, DEBUGASSERT(dns); *dns = NULL; - waitperform(data, 0); + if(waitperform(data, 0) < 0) + return CURLE_UNRECOVERABLE_POLL; #ifndef HAVE_CARES_GETADDRINFO /* Now that we've checked for any last minute results above, see if there are @@ -475,7 +479,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, else timeout_ms = 1000; - waitperform(data, timeout_ms); + if(waitperform(data, timeout_ms) < 0) + return CURLE_UNRECOVERABLE_POLL; result = Curl_resolver_is_resolved(data, entry); if(result || data->state.async.done) diff --git a/lib/easy.c b/lib/easy.c index 7781c8e16158c8..a31fdbfbae89e8 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -549,6 +549,8 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) /* wait for activity or timeout */ pollrc = Curl_poll(fds, numfds, ev->ms); + if(pollrc < 0) + return CURLE_UNRECOVERABLE_POLL; after = Curl_now(); diff --git a/lib/multi.c b/lib/multi.c index 8e58d785a9ecaa..ff8e5248df22f8 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1312,6 +1312,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi, #else pollrc = Curl_poll(ufds, nfds, timeout_ms); /* wait... */ #endif + if(pollrc < 0) + return CURLM_UNRECOVERABLE_POLL; if(pollrc > 0) { retcode = pollrc; diff --git a/lib/select.c b/lib/select.c index a48da82bacc174..cdae5e87e05d87 100644 --- a/lib/select.c +++ b/lib/select.c @@ -352,8 +352,12 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) value). */ r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms); - if(r <= 0) + if(r <= 0) { + if((r == -1) && (SOCKERRNO == EINTR)) + /* make EINTR from select or poll not a "lethal" error */ + r = 0; return r; + } r = 0; for(i = 0; i < nfds; i++) { diff --git a/lib/strerror.c b/lib/strerror.c index 781e26b69fb792..cc36769aa171d9 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -317,6 +317,9 @@ curl_easy_strerror(CURLcode error) case CURLE_SSL_CLIENTCERT: return "SSL Client Certificate required"; + case CURLE_UNRECOVERABLE_POLL: + return "Unrecoverable error in select/poll"; + /* error codes not used by current libcurl */ case CURLE_OBSOLETE20: case CURLE_OBSOLETE24: @@ -400,6 +403,9 @@ curl_multi_strerror(CURLMcode error) case CURLM_ABORTED_BY_CALLBACK: return "Operation was aborted by an application callback"; + case CURLM_UNRECOVERABLE_POLL: + return "Unrecoverable error in select/poll"; + case CURLM_LAST: break; } diff --git a/tests/data/test1538 b/tests/data/test1538 index 5157e36b7f9353..e21d0537f5deb9 100644 --- a/tests/data/test1538 +++ b/tests/data/test1538 @@ -131,7 +131,8 @@ e95: HTTP/3 error e96: QUIC connection error e97: proxy handshake error e98: SSL Client Certificate required -e99: Unknown error +e99: Unrecoverable error in select/poll +e100: Unknown error m-1: Please call curl_multi_perform() soon m0: No error m1: Invalid multi handle @@ -145,7 +146,8 @@ m8: API function called from within callback m9: Wakeup is unavailable or failed m10: A libcurl function was given a bad argument m11: Operation was aborted by an application callback -m12: Unknown error +m12: Unrecoverable error in select/poll +m13: Unknown error s0: No error s1: Unknown share option s2: Share currently in use