socket: introduce SOCK_EAGAIN() and use it

To contain the logic of checking for both `EWOULDBLOCK` and/or `EAGAIN`
depending on platform/availability. Also to avoid checking for both if
they mapp to the same value, and to avoid PP guards around use.

This also ensures `EAGAIN` is consistently not checked on Windows, where
headers defined it, but `SOCKERRNO` never returns it, because curl maps
it to `WSAGetLastError()`.

If they map to the same value, checking them both in an `if` expression
trips GCC warning `-Wlogical-op` (the same way it triggers duplicate
case value error in `switch`).

Also:
- replace two `switch()` statements with the new macro.
- tests/server/sws: make two outliers use the new macro that were only
  checking for `EWOULDBLOCK` before this patch, in `connect_to()`.
- move variables to the left-side of expressions, where missing.
- rustls: use a variant of this macro that uses raw `EWOULDBLOCK`.
  Tried tracing it back to the origins, but I couldn't figure out if
  this is working as expected on all supported Windows versions in
  Rust. It seems to be using `GetLastError()`, according to
  https://docs.rs/system_error/0.2.0/system_error/, which would be
  probably incorrect.

Notes:
- it's probably a good idea to assign `SOCKERRNO` to a variable before
  passing it to this macro.

Cherry-picked from #21893

Closes #21992
This commit is contained in:
Viktor Szakats 2026-06-08 01:21:44 +02:00
parent 7c51a33877
commit 879a1514c3
No known key found for this signature in database
7 changed files with 63 additions and 95 deletions

View file

@ -976,7 +976,7 @@ static int sws_send_doc(curl_socket_t sock, struct sws_httprequest *req)
retry:
written = swrite(sock, buffer, num);
if(written < 0) {
if((SOCKEWOULDBLOCK == SOCKERRNO) || (EAGAIN == SOCKERRNO)) {
if(SOCK_EAGAIN(SOCKERRNO)) {
curlx_wait_ms(10);
goto retry;
}
@ -1133,8 +1133,7 @@ static int sws_get_request(curl_socket_t sock, struct sws_httprequest *req)
logmsg("Got %zd bytes from client", got);
}
if((got == -1) &&
((SOCKERRNO == EAGAIN) || (SOCKERRNO == SOCKEWOULDBLOCK))) {
if((got == -1) && SOCK_EAGAIN(SOCKERRNO)) {
int rc;
fd_set input;
fd_set output;
@ -1194,7 +1193,7 @@ static int sws_get_request(curl_socket_t sock, struct sws_httprequest *req)
else if(got < 0) {
char errbuf[STRERROR_LEN];
int error = SOCKERRNO;
if(EAGAIN == error || SOCKEWOULDBLOCK == error) {
if(SOCK_EAGAIN(error)) {
/* nothing to read at the moment */
return 0;
}
@ -1335,7 +1334,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
if(rc) {
error = SOCKERRNO;
if((error == SOCKEINPROGRESS) || (error == SOCKEWOULDBLOCK)) {
if((error == SOCKEINPROGRESS) || SOCK_EAGAIN(error)) {
fd_set output;
struct timeval timeout = { 0 };
timeout.tv_sec = 1; /* 1000 ms */
@ -1353,7 +1352,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
error = SOCKERRNO;
if((error == 0) || (SOCKEISCONN == error))
goto success;
else if((error != SOCKEINPROGRESS) && (error != SOCKEWOULDBLOCK))
else if((error != SOCKEINPROGRESS) && !SOCK_EAGAIN(error))
goto error;
}
else if(!rc) {
@ -1822,7 +1821,7 @@ static curl_socket_t accept_connection(curl_socket_t sock)
if(msgsock == CURL_SOCKET_BAD) {
error = SOCKERRNO;
if(EAGAIN == error || SOCKEWOULDBLOCK == error) {
if(SOCK_EAGAIN(error)) {
/* nothing to accept */
return 0;
}