From 6e708ce14432066755775102b09845fccc843036 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 26 Dec 2016 18:28:18 +0100 Subject: [PATCH] Problem: socketpair leaks file on fork+exec Solution: if available, call socketpair with SOCK_CLOEXEC flag to make the process close the socket on fork+exec --- src/signaler.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/signaler.cpp b/src/signaler.cpp index 5922cda7..5a0b8ddc 100644 --- a/src/signaler.cpp +++ b/src/signaler.cpp @@ -644,13 +644,29 @@ int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_) #else // All other implementations support socketpair() int sv [2]; - int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv); + int type = SOCK_STREAM; + // Setting this option result in sane behaviour when exec() functions + // are used. Old sockets are closed and don't block TCP ports, avoid + // leaks, etc. +#if defined ZMQ_HAVE_SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif + int rc = socketpair (AF_UNIX, type, 0, sv); if (rc == -1) { errno_assert (errno == ENFILE || errno == EMFILE); *w_ = *r_ = -1; return -1; } else { + // If there's no SOCK_CLOEXEC, let's try the second best option. Note that + // race condition can cause socket not to be closed (if fork happens + // between socket creation and this point). +#if !defined ZMQ_HAVE_SOCK_CLOEXEC && defined FD_CLOEXEC + rc = fcntl (sv [0], F_SETFD, FD_CLOEXEC); + errno_assert (rc != -1); + rc = fcntl (sv [1], F_SETFD, FD_CLOEXEC); + errno_assert (rc != -1); +#endif *w_ = sv [0]; *r_ = sv [1]; return 0;