Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Aug 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions src/ip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
#include "tcp.hpp"
#ifdef ZMQ_HAVE_IPC
#include "ipc_address.hpp"
// Don't try ipc if it fails once
namespace zmq
{
static bool try_ipc_first = true;
}
#endif

#include <direct.h>
Expand Down Expand Up @@ -555,9 +560,14 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)

// It appears that a lack of runtime AF_UNIX support
// 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;

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.
const SOCKET listener = open_socket (AF_UNIX, SOCK_STREAM, 0);
if (listener == retired_fd) {
Expand Down Expand Up @@ -585,8 +595,7 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
goto error_closelistener;
}
// if we got here, ipc should be working,
// so raise any remaining errors
ipc_fallback_on_tcpip = false;
// but there are at least some cases where connect can still fail

// Listen for incoming connections.
rc = listen (listener, 1);
Expand All @@ -597,24 +606,28 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)

rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&lcladdr),
&lcladdr_len);
wsa_assert (rc != -1);
wsa_assert (rc == 0);

// Create the client socket.
*w_ = open_socket (AF_UNIX, SOCK_STREAM, 0);
if (*w_ == -1) {
if (*w_ == retired_fd) {
errno = wsa_error_to_errno (WSAGetLastError ());
goto error_closelistener;
}

// Connect to the remote peer.
rc = ::connect (*w_, reinterpret_cast<const struct sockaddr *> (&lcladdr),
lcladdr_len);
if (rc == -1) {
if (rc != 0) {
errno = wsa_error_to_errno (WSAGetLastError ());
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);
errno_assert (*r_ != -1);
wsa_assert (*r_ != retired_fd);

// Close the listener socket, we don't need it anymore.
rc = closesocket (listener);
Expand All @@ -636,6 +649,7 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
saved_errno = errno;
rc = closesocket (*w_);
wsa_assert (rc == 0);
*w_ = retired_fd;
errno = saved_errno;

error_closelistener:
Expand Down Expand Up @@ -663,9 +677,13 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)

try_tcpip:
// try to fallback to TCP/IP
// TODO: maybe remember this decision permanently?
#endif

rc = make_fdpair_tcpip (r_, w_);
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_);
#elif defined ZMQ_HAVE_OPENVMS

Expand Down
Loading