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

@ -232,16 +232,9 @@ static int wakeup_inet(curl_socket_t socks[2], bool nonblocking)
/* Do not block forever */
if(curlx_timediff_ms(curlx_now(), start) > (60 * 1000))
goto error;
if(
#ifdef USE_WINSOCK
/* This is how Windows does it */
(SOCKEWOULDBLOCK == sockerr)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it
returned due to its inability to send off data without
blocking. We therefore treat both error codes the same here */
(SOCKEWOULDBLOCK == sockerr) || (EAGAIN == sockerr) ||
(SOCKEINTR == sockerr) || (SOCKEINPROGRESS == sockerr)
if(SOCK_EAGAIN(sockerr)
#ifndef USE_WINSOCK
|| (sockerr == SOCKEINTR) || (sockerr == SOCKEINPROGRESS)
#endif
) {
continue;
@ -320,15 +313,12 @@ int Curl_wakeup_signal(curl_socket_t socks[2])
err = 0;
if(wakeup_write(socks[1], buf, sizeof(buf)) < 0) {
err = SOCKERRNO;
#ifdef USE_WINSOCK
if(err == SOCKEWOULDBLOCK)
err = 0; /* wakeup is already ongoing */
#else
if(SOCKEINTR == err)
#ifndef USE_WINSOCK
if(err == SOCKEINTR)
continue;
if((err == SOCKEWOULDBLOCK) || (err == EAGAIN))
err = 0; /* wakeup is already ongoing */
#endif
if(SOCK_EAGAIN(err))
err = 0; /* wakeup is already ongoing */
}
break;
}
@ -346,15 +336,13 @@ CURLcode Curl_wakeup_consume(curl_socket_t socks[2], bool all)
if(!rc)
break;
else if(rc < 0) {
#ifdef USE_WINSOCK
if(SOCKERRNO == SOCKEWOULDBLOCK)
break;
#else
if(SOCKEINTR == SOCKERRNO)
int sockerr = SOCKERRNO;
#ifndef USE_WINSOCK
if(sockerr == SOCKEINTR)
continue;
if((SOCKERRNO == SOCKEWOULDBLOCK) || (SOCKERRNO == EAGAIN))
break;
#endif
if(SOCK_EAGAIN(sockerr))
break;
result = CURLE_READ_ERROR;
break;
}