Commit e175fe21 authored by Peter J. Holzer's avatar Peter J. Holzer

Avoid race condition with accept4 where available

Linux provides accept4(2) which will return a socket with FD_CLOEXEC set
when called with the SOCK_CLOEXEC flag. So call this when available and
fall back to fcntl(..., FD_CLOEXEC) if not.
parent 5e684172
...@@ -390,7 +390,11 @@ zmq::fd_t zmq::ipc_listener_t::accept () ...@@ -390,7 +390,11 @@ zmq::fd_t zmq::ipc_listener_t::accept ()
// The situation where connection cannot be accepted due to insufficient // The situation where connection cannot be accepted due to insufficient
// resources is considered valid and treated by ignoring the connection. // resources is considered valid and treated by ignoring the connection.
zmq_assert (s != retired_fd); zmq_assert (s != retired_fd);
#if defined ZMQ_HAVE_SOCK_CLOEXEC
fd_t sock = ::accept4 (s, (struct sockaddr *) &ss, &ss_len, SOCK_CLOEXEC);
#else
fd_t sock = ::accept (s, NULL, NULL); fd_t sock = ::accept (s, NULL, NULL);
#endif
if (sock == -1) { if (sock == -1) {
errno_assert (errno == EAGAIN || errno == EWOULDBLOCK || errno_assert (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == EINTR || errno == ECONNABORTED || errno == EPROTO || errno == EINTR || errno == ECONNABORTED || errno == EPROTO ||
...@@ -398,9 +402,9 @@ zmq::fd_t zmq::ipc_listener_t::accept () ...@@ -398,9 +402,9 @@ zmq::fd_t zmq::ipc_listener_t::accept ()
return retired_fd; return retired_fd;
} }
#if !defined ZMQ_HAVE_SOCK_CLOEXEC && defined FD_CLOEXEC
// Race condition can cause socket not to be closed (if fork happens // Race condition can cause socket not to be closed (if fork happens
// between accept and this point). // between accept and this point).
#ifdef FD_CLOEXEC
int rc = fcntl (sock, F_SETFD, FD_CLOEXEC); int rc = fcntl (sock, F_SETFD, FD_CLOEXEC);
errno_assert (rc != -1); errno_assert (rc != -1);
#endif #endif
......
...@@ -273,7 +273,11 @@ zmq::fd_t zmq::tcp_listener_t::accept () ...@@ -273,7 +273,11 @@ zmq::fd_t zmq::tcp_listener_t::accept ()
#else #else
socklen_t ss_len = sizeof (ss); socklen_t ss_len = sizeof (ss);
#endif #endif
#if defined ZMQ_HAVE_SOCK_CLOEXEC
fd_t sock = ::accept4 (s, (struct sockaddr *) &ss, &ss_len, SOCK_CLOEXEC);
#else
fd_t sock = ::accept (s, (struct sockaddr *) &ss, &ss_len); fd_t sock = ::accept (s, (struct sockaddr *) &ss, &ss_len);
#endif
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
...@@ -299,9 +303,9 @@ zmq::fd_t zmq::tcp_listener_t::accept () ...@@ -299,9 +303,9 @@ zmq::fd_t zmq::tcp_listener_t::accept ()
} }
#endif #endif
#if !defined ZMQ_HAVE_SOCK_CLOEXEC && defined FD_CLOEXEC
// Race condition can cause socket not to be closed (if fork happens // Race condition can cause socket not to be closed (if fork happens
// between accept and this point). // between accept and this point).
#ifdef FD_CLOEXEC
int rc = fcntl (sock, F_SETFD, FD_CLOEXEC); int rc = fcntl (sock, F_SETFD, FD_CLOEXEC);
errno_assert (rc != -1); errno_assert (rc != -1);
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment