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:
parent
0ed7a08cd9
commit
1f4dd54f94
38
src/ip.cpp
38
src/ip.cpp
@ -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
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user