Client websocket reconnect fails on windows after implementation of fix for #3272
With commit b99c89cfc965 ("Fix Websockets PING not being sent on Windows.") lib/net_mosq.c has been changed to use the new macro WINDOWS_SET_ERRNO directly after a connect() syscall at three locations. In each of those locations, the socket is either explicitly set to nonblocking or may be set to nonblocking.
With the change for #3272, retrieval of errno via WSAGetLastError() will not be done if errno has been set to EAGAIN for unknown or unrelated reasons before.
Comparing this to the microsoft documentation "connect function (winsock2.h)" https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect ...
Return value
...
With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. ...
... connect may return !=0 and WSAGetLastError must be checked for WSAEWOULDBLOCK in nonblocking context.
Manifestation of this problem: an implementation using mosquitto-2.0.22 did not reconnect to a mqtt broker after the broker has been temporarily shut down. This problem has not been present in 2.0.21 and may be fixed in 2.0.22 by reverting commit b99c89cfc965 for lib/net_mosq.c.
Proposal for a fix: `commit 740da754639fa45b9211ca8cf4db7c7e0adab384 (HEAD) Author: Alexander Kurz [email protected] Date: Wed Dec 10 16:36:39 2025 +0100
Fix client websocket reconnect on windows
On windows, the connect function (winsock2.h) may return !=0 and
WSAGetLastError must be checked for WSAEWOULDBLOCK in nonblocking context.
With commit b99c89cfc965 ("Fix Websockets PING not being sent on Windows.")
update of errno will however be skipped if errno has bee set to EAGAIN
for unrelated reasons before.
Revert the usage of WINDOWS_SET_ERRNO in lib/net_mosq.c to fix problems
of failing client reconnects to a server that went temporarily offline.
Fixes: b99c89cfc965 ("Fix Websockets PING not being sent on Windows.")
Closes: #3424
Signed-off-by: Alexander Kurz <[email protected]>
diff --git a/lib/net_mosq.c b/lib/net_mosq.c index d9eb81e0..71794290 100644 --- a/lib/net_mosq.c +++ b/lib/net_mosq.c @@ -361,7 +361,9 @@ int net__try_connect_step2(struct mosquitto *mosq, uint16_t port, mosq_sock_t *s }
rc = connect(*sock, rp->ai_addr, rp->ai_addrlen);
-
WINDOWS_SET_ERRNO();
+#ifdef WIN32
-
errno = WSAGetLastError();
+#endif if(rc == 0 || errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK){ if(rc < 0 && (errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK)){ rc = MOSQ_ERR_CONN_PENDING; @@ -459,7 +461,9 @@ static int net__try_connect_tcp(const char *host, uint16_t port, mosq_sock_t *so }
rc = connect(*sock, rp->ai_addr, rp->ai_addrlen);
-
WINDOWS_SET_ERRNO();
+#ifdef WIN32
-
errno = WSAGetLastError();
+#endif if(rc == 0 || errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK){ if(rc < 0 && (errno == EINPROGRESS || errno == COMPAT_EWOULDBLOCK)){ rc = MOSQ_ERR_CONN_PENDING; @@ -1130,7 +1134,9 @@ int net__socketpair(mosq_sock_t *pairR, mosq_sock_t *pairW) continue; } if(connect(spR, (struct sockaddr *)&ss, ss_len) < 0){
-
WINDOWS_SET_ERRNO();
+#ifdef WIN32
-
errno = WSAGetLastError();
+#endif if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){ COMPAT_CLOSE(spR); COMPAT_CLOSE(listensock); @@ -1139,7 +1145,9 @@ int net__socketpair(mosq_sock_t *pairR, mosq_sock_t *pairW) } spW = accept(listensock, NULL, 0); if(spW == -1){
-
WINDOWS_SET_ERRNO();
+#ifdef WIN32
-
errno = WSAGetLastError();
+#endif if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){ COMPAT_CLOSE(spR); COMPAT_CLOSE(listensock); `