Skip to content

Commit 1f4dd54

Browse files
authored
Problem: ipc connect can fail on Windows, even after bind (#4734)
* ipc connect can fail, even after bind
1 parent 0ed7a08 commit 1f4dd54

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

src/ip.cpp

+28-10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
#include "tcp.hpp"
2424
#ifdef ZMQ_HAVE_IPC
2525
#include "ipc_address.hpp"
26+
// Don't try ipc if it fails once
27+
namespace zmq
28+
{
29+
static bool try_ipc_first = true;
30+
}
2631
#endif
2732

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

556561
// It appears that a lack of runtime AF_UNIX support
557562
// can fail in more than one way.
558-
// At least: open_socket can fail or later in bind
563+
// At least: open_socket can fail or later in bind or even in connect after bind
559564
bool ipc_fallback_on_tcpip = true;
560565

566+
if (!zmq::try_ipc_first) {
567+
// a past ipc attempt failed, skip straight to try_tcpip in the future;
568+
goto try_tcpip;
569+
}
570+
561571
// Create a listening socket.
562572
const SOCKET listener = open_socket (AF_UNIX, SOCK_STREAM, 0);
563573
if (listener == retired_fd) {
@@ -585,8 +595,7 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
585595
goto error_closelistener;
586596
}
587597
// if we got here, ipc should be working,
588-
// so raise any remaining errors
589-
ipc_fallback_on_tcpip = false;
598+
// but there are at least some cases where connect can still fail
590599

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

598607
rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&lcladdr),
599608
&lcladdr_len);
600-
wsa_assert (rc != -1);
609+
wsa_assert (rc == 0);
601610

602611
// Create the client socket.
603612
*w_ = open_socket (AF_UNIX, SOCK_STREAM, 0);
604-
if (*w_ == -1) {
613+
if (*w_ == retired_fd) {
605614
errno = wsa_error_to_errno (WSAGetLastError ());
606615
goto error_closelistener;
607616
}
608617

609618
// Connect to the remote peer.
610619
rc = ::connect (*w_, reinterpret_cast<const struct sockaddr *> (&lcladdr),
611620
lcladdr_len);
612-
if (rc == -1) {
621+
if (rc != 0) {
622+
errno = wsa_error_to_errno (WSAGetLastError ());
613623
goto error_closeclient;
614624
}
625+
// if we got here, ipc should be working,
626+
// so raise any remaining errors
627+
ipc_fallback_on_tcpip = false;
615628

616629
*r_ = accept (listener, NULL, NULL);
617-
errno_assert (*r_ != -1);
630+
wsa_assert (*r_ != retired_fd);
618631

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

641655
error_closelistener:
@@ -663,9 +677,13 @@ int zmq::make_fdpair (fd_t *r_, fd_t *w_)
663677

664678
try_tcpip:
665679
// try to fallback to TCP/IP
666-
// TODO: maybe remember this decision permanently?
667-
#endif
668-
680+
rc = make_fdpair_tcpip (r_, w_);
681+
if (rc == 0 && zmq::try_ipc_first) {
682+
// ipc didn't work but tcp/ip did; skip ipc in the future
683+
zmq::try_ipc_first = false;
684+
}
685+
return rc;
686+
#endif // ZMQ_HAVE_IPC
669687
return make_fdpair_tcpip (r_, w_);
670688
#elif defined ZMQ_HAVE_OPENVMS
671689

0 commit comments

Comments
 (0)