0
0
mirror of https://github.com/zeromq/libzmq.git synced 2024-12-26 14:51:01 +08:00

Problem: ipc connect can fail on Windows, even after bind (#4734)

* ipc connect can fail, even after bind
This commit is contained in:
Min RK 2024-08-26 06:57:23 -07:00 committed by GitHub
parent 0ed7a08cd9
commit 1f4dd54f94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -23,6 +23,11 @@
#include "tcp.hpp" #include "tcp.hpp"
#ifdef ZMQ_HAVE_IPC #ifdef ZMQ_HAVE_IPC
#include "ipc_address.hpp" #include "ipc_address.hpp"
// Don't try ipc if it fails once
namespace zmq
{
static bool try_ipc_first = true;
}
#endif #endif
#include <direct.h> #include <direct.h>
@ -555,9 +560,14 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
// It appears that a lack of runtime AF_UNIX support // It appears that a lack of runtime AF_UNIX support
// can fail in more than one way. // can fail in more than one way.
// At least: open_socket can fail or later in bind // At least: open_socket can fail or later in bind or even in connect after bind
bool ipc_fallback_on_tcpip = true; bool ipc_fallback_on_tcpip = true;
if (!zmq::try_ipc_first) {
// a past ipc attempt failed, skip straight to try_tcpip in the future;
goto try_tcpip;
}
// Create a listening socket. // Create a listening socket.
const SOCKET listener = open_socket (AF_UNIX, SOCK_STREAM, 0); const SOCKET listener = open_socket (AF_UNIX, SOCK_STREAM, 0);
if (listener == retired_fd) { if (listener == retired_fd) {
@ -585,8 +595,7 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
goto error_closelistener; goto error_closelistener;
} }
// if we got here, ipc should be working, // if we got here, ipc should be working,
// so raise any remaining errors // but there are at least some cases where connect can still fail
ipc_fallback_on_tcpip = false;
// Listen for incoming connections. // Listen for incoming connections.
rc = listen (listener, 1); rc = listen (listener, 1);
@ -597,11 +606,11 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&lcladdr), rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&lcladdr),
&lcladdr_len); &lcladdr_len);
wsa_assert (rc != -1); wsa_assert (rc == 0);
// Create the client socket. // Create the client socket.
*w_ = open_socket (AF_UNIX, SOCK_STREAM, 0); *w_ = open_socket (AF_UNIX, SOCK_STREAM, 0);
if (*w_ == -1) { if (*w_ == retired_fd) {
errno = wsa_error_to_errno (WSAGetLastError ()); errno = wsa_error_to_errno (WSAGetLastError ());
goto error_closelistener; goto error_closelistener;
} }
@ -609,12 +618,16 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
// Connect to the remote peer. // Connect to the remote peer.
rc = ::connect (*w_, reinterpret_cast<const struct sockaddr *> (&lcladdr), rc = ::connect (*w_, reinterpret_cast<const struct sockaddr *> (&lcladdr),
lcladdr_len); lcladdr_len);
if (rc == -1) { if (rc != 0) {
errno = wsa_error_to_errno (WSAGetLastError ());
goto error_closeclient; goto error_closeclient;
} }
// if we got here, ipc should be working,
// so raise any remaining errors
ipc_fallback_on_tcpip = false;
*r_ = accept (listener, NULL, NULL); *r_ = accept (listener, NULL, NULL);
errno_assert (*r_ != -1); wsa_assert (*r_ != retired_fd);
// Close the listener socket, we don't need it anymore. // Close the listener socket, we don't need it anymore.
rc = closesocket (listener); rc = closesocket (listener);
@ -636,6 +649,7 @@ error_closeclient:
saved_errno = errno; saved_errno = errno;
rc = closesocket (*w_); rc = closesocket (*w_);
wsa_assert (rc == 0); wsa_assert (rc == 0);
*w_ = retired_fd;
errno = saved_errno; errno = saved_errno;
error_closelistener: error_closelistener:
@ -663,9 +677,13 @@ error_closelistener:
try_tcpip: try_tcpip:
// try to fallback to TCP/IP // try to fallback to TCP/IP
// TODO: maybe remember this decision permanently? rc = make_fdpair_tcpip (r_, w_);
#endif if (rc == 0 && zmq::try_ipc_first) {
// ipc didn't work but tcp/ip did; skip ipc in the future
zmq::try_ipc_first = false;
}
return rc;
#endif // ZMQ_HAVE_IPC
return make_fdpair_tcpip (r_, w_); return make_fdpair_tcpip (r_, w_);
#elif defined ZMQ_HAVE_OPENVMS #elif defined ZMQ_HAVE_OPENVMS