Problem: epoll leaks socket on fork+exec

Solution: if available, use epoll_create1 with EPOLL_CLOEXEC flag to
make the process close the socket on fork+exec
This commit is contained in:
Luca Boccassi 2016-12-26 18:01:36 +01:00
parent 16439e42d2
commit 211898d243
4 changed files with 46 additions and 2 deletions

View File

@ -101,6 +101,10 @@ if (POLLER STREQUAL "")
set (CMAKE_REQUIRED_INCLUDES)
if (HAVE_EPOLL)
set (POLLER "epoll")
check_function_exists (epoll_create1 HAVE_EPOLL_CLOEXEC)
if (HAVE_EPOLL_CLOEXEC)
set (ZMQ_USE_EPOLL_CLOEXEC 1)
endif ()
endif ()
endif ()

View File

@ -801,6 +801,7 @@ kqueue();
dnl ################################################################################
dnl # LIBZMQ_CHECK_POLLER_EPOLL_RUN([action-if-found], [action-if-not-found]) #
dnl # LIBZMQ_CHECK_POLLER_EPOLL_CLOEXEC([action-if-found], [action-if-not-found]) #
dnl # Checks epoll polling system can actually run #
dnl # For cross-compile, only requires that epoll can link #
dnl ################################################################################
@ -828,6 +829,30 @@ epoll_create(10);
)
}])
AC_DEFUN([LIBZMQ_CHECK_POLLER_EPOLL_CLOEXEC], [{
AC_RUN_IFELSE([
AC_LANG_PROGRAM([
#include <sys/epoll.h>
],[[
struct epoll_event t_ev;
int r;
r = epoll_create1(EPOLL_CLOEXEC);
return(r < 0);
]])],
[$1],[$2],[
AC_LINK_IFELSE([
AC_LANG_PROGRAM([
#include <sys/epoll.h>
],[[
struct epoll_event t_ev;
epoll_create1(EPOLL_CLOEXEC);
]])],
[$1], [$2]
)
]
)
}])
dnl ################################################################################
dnl # LIBZMQ_CHECK_POLLER_DEVPOLL([action-if-found], [action-if-not-found]) #
dnl # Checks devpoll polling system #
@ -938,10 +963,17 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{
])
;;
epoll)
LIBZMQ_CHECK_POLLER_EPOLL([
AC_MSG_NOTICE([Using 'epoll' polling system])
LIBZMQ_CHECK_POLLER_EPOLL_CLOEXEC([
AC_MSG_NOTICE([Using 'epoll' polling system with CLOEXEC])
AC_DEFINE(ZMQ_USE_EPOLL, 1, [Use 'epoll' polling system])
AC_DEFINE(ZMQ_USE_EPOLL_CLOEXEC, 1, [Use 'epoll' polling system with CLOEXEC])
poller_found=1
],[
LIBZMQ_CHECK_POLLER_EPOLL([
AC_MSG_NOTICE([Using 'epoll' polling system with CLOEXEC])
AC_DEFINE(ZMQ_USE_EPOLL, 1, [Use 'epoll' polling system])
poller_found=1
])
])
;;
devpoll)

View File

@ -3,6 +3,7 @@
#cmakedefine ZMQ_USE_KQUEUE
#cmakedefine ZMQ_USE_EPOLL
#cmakedefine ZMQ_USE_EPOLL_CLOEXEC
#cmakedefine ZMQ_USE_DEVPOLL
#cmakedefine ZMQ_USE_POLL
#cmakedefine ZMQ_USE_SELECT

View File

@ -48,7 +48,14 @@ zmq::epoll_t::epoll_t (const zmq::ctx_t &ctx_) :
ctx(ctx_),
stopping (false)
{
#ifdef ZMQ_USE_EPOLL_CLOEXEC
// 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.
epoll_fd = epoll_create1 (EPOLL_CLOEXEC);
#else
epoll_fd = epoll_create (1);
#endif
errno_assert (epoll_fd != -1);
}