From d326434b371b94c4a98f66df69566f5a28070fcd Mon Sep 17 00:00:00 2001 From: Simon Giesecke Date: Tue, 22 May 2018 15:57:20 +0200 Subject: [PATCH] Problem: API poller cannot be set independently from I/O thread poller, poll I/O thread poller broken on Windows Solution: change platform definitions to separate API poller from I/O thread poller, disallow configuring poll I/O thread poller on Windows --- CMakeLists.txt | 23 ++++++++++--- acinclude.m4 | 62 +++++++++++++++++++++++++----------- builds/cmake/platform.hpp.in | 15 +++++---- src/devpoll.cpp | 2 +- src/devpoll.hpp | 2 +- src/epoll.cpp | 2 +- src/epoll.hpp | 2 +- src/kqueue.cpp | 2 +- src/kqueue.hpp | 2 +- src/poll.cpp | 12 +------ src/poll.hpp | 10 ++++-- src/poller.hpp | 34 +++++++++++--------- src/pollset.cpp | 2 +- src/pollset.hpp | 2 +- src/select.cpp | 2 +- src/select.hpp | 2 +- src/windows.hpp | 2 +- 17 files changed, 110 insertions(+), 68 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f83f8ae..82409b2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,10 @@ if (WITH_MILITANT) add_definitions(-DZMQ_ACT_MILITANT) endif() -set (POLLER "" CACHE STRING "Choose polling system. valid values are +set (API_POLLER "" CACHE STRING "Choose polling system for zmq_poll(er)_*. valid values are + poll or select [default=poll unless POLLER=select]") + +set (POLLER "" CACHE STRING "Choose polling system for I/O threads. valid values are kqueue, epoll, devpoll, pollset, poll or select [default=autodetect]") include (CheckFunctionExists) @@ -117,7 +120,7 @@ if (POLLER STREQUAL "") set (POLLER "epoll") check_function_exists (epoll_create1 HAVE_EPOLL_CLOEXEC) if (HAVE_EPOLL_CLOEXEC) - set (ZMQ_USE_EPOLL_CLOEXEC 1) + set (ZMQ_IOTHREAD_POLLER_USE_EPOLL_CLOEXEC 1) endif () endif () endif () @@ -172,13 +175,25 @@ if (POLLER STREQUAL "kqueue" OR POLLER STREQUAL "pollset" OR POLLER STREQUAL "poll" OR POLLER STREQUAL "select") - message (STATUS "Detected ${POLLER} polling method") + message (STATUS "Using polling method in I/O threads: ${POLLER}") string (TOUPPER ${POLLER} UPPER_POLLER) - set (ZMQ_USE_${UPPER_POLLER} 1) + set (ZMQ_IOTHREAD_POLLER_USE_${UPPER_POLLER} 1) else () message (FATAL_ERROR "Invalid polling method") endif () +if (API_POLLER STREQUAL "") + if (POLLER STREQUAL "select") + set (API_POLLER "select") + else() + set (API_POLLER "poll") + endif() +endif() + +message (STATUS "Using polling method in zmq_poll(er)_* API: ${API_POLLER}") + string (TOUPPER ${API_POLLER} UPPER_API_POLLER) +set (ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1) + include (TestZMQVersion) if (NOT CMAKE_CROSSCOMPILING) include (ZMQSourceRunChecks) diff --git a/acinclude.m4 b/acinclude.m4 index d96a6215..891d9cfe 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1052,7 +1052,12 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{ # Allow user to override poller autodetection AC_ARG_WITH([poller], [AS_HELP_STRING([--with-poller], - [choose polling system manually. Valid values are 'kqueue', 'epoll', 'devpoll', 'pollset', 'poll', 'select', or 'auto'. [default=auto]])]) + [choose I/O thread polling system manually. Valid values are 'kqueue', 'epoll', 'devpoll', 'pollset', 'poll', 'select', or 'auto'. [default=auto]])]) + + # Allow user to override poller autodetection + AC_ARG_WITH([api_poller], + [AS_HELP_STRING([--with-api-poller], + [choose zmq_poll(er)_* API polling system manually. Valid values are 'poll', 'select', or 'auto'. [default=auto]])]) if test "x$with_poller" == "x"; then pollers=auto @@ -1065,14 +1070,14 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{ fi # try to find suitable polling system. the order of testing is: - AC_MSG_NOTICE([Choosing polling system from '$pollers'...]) + AC_MSG_NOTICE([Choosing I/O thread polling system from '$pollers'...]) poller_found=0 for poller in $pollers; do case "$poller" in kqueue) LIBZMQ_CHECK_POLLER_KQUEUE([ - AC_MSG_NOTICE([Using 'kqueue' polling system]) - AC_DEFINE(ZMQ_USE_KQUEUE, 1, [Use 'kqueue' polling system]) + AC_MSG_NOTICE([Using 'kqueue' I/O thread polling system]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_KQUEUE, 1, [Use 'kqueue' I/O thread polling system]) poller_found=1 ]) ;; @@ -1084,17 +1089,17 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{ # that ZMQ has from Linux systems. Unless you undertake # to fix the integration, do not disable this exception # and use select() or poll() on Solarish OSes for now. - AC_MSG_NOTICE([NOT using 'epoll' polling system on '$host_os']) ;; + AC_MSG_NOTICE([NOT using 'epoll' I/O thread polling system on '$host_os']) ;; *) 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]) + AC_MSG_NOTICE([Using 'epoll' I/O thread polling system with CLOEXEC]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_EPOLL, 1, [Use 'epoll' I/O thread polling system]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_EPOLL_CLOEXEC, 1, [Use 'epoll' I/O thread 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]) + AC_MSG_NOTICE([Using 'epoll' I/O thread polling system with CLOEXEC]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_EPOLL, 1, [Use 'epoll' I/O thread polling system]) poller_found=1 ]) ]) @@ -1103,29 +1108,29 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{ ;; devpoll) LIBZMQ_CHECK_POLLER_DEVPOLL([ - AC_MSG_NOTICE([Using 'devpoll' polling system]) - AC_DEFINE(ZMQ_USE_DEVPOLL, 1, [Use 'devpoll' polling system]) + AC_MSG_NOTICE([Using 'devpoll' I/O thread polling system]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_DEVPOLL, 1, [Use 'devpoll' I/O thread polling system]) poller_found=1 ]) ;; pollset) LIBZMQ_CHECK_POLLER_POLLSET([ - AC_MSG_NOTICE([Using 'pollset' polling system]) - AC_DEFINE(ZMQ_USE_POLLSET, 1, [Use 'pollset' polling system]) + AC_MSG_NOTICE([Using 'pollset' I/O thread polling system]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_POLLSET, 1, [Use 'pollset' I/O thread polling system]) poller_found=1 ]) ;; poll) LIBZMQ_CHECK_POLLER_POLL([ - AC_MSG_NOTICE([Using 'poll' polling system]) - AC_DEFINE(ZMQ_USE_POLL, 1, [Use 'poll' polling system]) + AC_MSG_NOTICE([Using 'poll' I/O thread polling system]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_POLL, 1, [Use 'poll' I/O thread polling system]) poller_found=1 ]) ;; select) LIBZMQ_CHECK_POLLER_SELECT([ - AC_MSG_NOTICE([Using 'select' polling system]) - AC_DEFINE(ZMQ_USE_SELECT, 1, [Use 'select' polling system]) + AC_MSG_NOTICE([Using 'select' I/O thread polling system]) + AC_DEFINE(ZMQ_IOTHREAD_POLLER_USE_SELECT, 1, [Use 'select' I/O thread polling system]) poller_found=1 ]) ;; @@ -1135,4 +1140,25 @@ AC_DEFUN([LIBZMQ_CHECK_POLLER], [{ if test $poller_found -eq 0; then AC_MSG_ERROR([None of '$pollers' are valid pollers on this platform]) fi + if test "x$with_api_poller" == "x"; then + with_api_poller=auto + fi + if test "x$with_api_poller" == "xauto"; then + if test $poller == "select"; then + api_poller=select + else + api_poller=poll + fi + else + api_poller=$with_api_poller + fi + if test "$api_poller" == "select"; then + AC_MSG_NOTICE([Using 'select' zmq_poll(er)_* API polling system]) + AC_DEFINE(ZMQ_POLL_BASED_ON_SELECT, 1, [Use 'select' zmq_poll(er)_* API polling system]) + elif test "$api_poller" == "poll"; then + AC_MSG_NOTICE([Using 'poll' zmq_poll(er)_* API polling system]) + AC_DEFINE(ZMQ_POLL_BASED_ON_POLL, 1, [Use 'poll' zmq_poll(er)_* API polling system]) + else + AC_MSG_ERROR([Invalid API poller '$api_poller' specified]) + fi }]) diff --git a/builds/cmake/platform.hpp.in b/builds/cmake/platform.hpp.in index 18d02d2b..8c8e6cf2 100644 --- a/builds/cmake/platform.hpp.in +++ b/builds/cmake/platform.hpp.in @@ -1,12 +1,15 @@ #ifndef __ZMQ_PLATFORM_HPP_INCLUDED__ #define __ZMQ_PLATFORM_HPP_INCLUDED__ -#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 +#cmakedefine ZMQ_IOTHREAD_POLLER_USE_KQUEUE +#cmakedefine ZMQ_IOTHREAD_POLLER_USE_EPOLL +#cmakedefine ZMQ_IOTHREAD_POLLER_USE_EPOLL_CLOEXEC +#cmakedefine ZMQ_IOTHREAD_POLLER_USE_DEVPOLL +#cmakedefine ZMQ_IOTHREAD_POLLER_USE_POLL +#cmakedefine ZMQ_IOTHREAD_POLLER_USE_SELECT + +#cmakedefine ZMQ_POLL_BASED_ON_SELECT +#cmakedefine ZMQ_POLL_BASED_ON_POLL #cmakedefine ZMQ_FORCE_MUTEXES diff --git a/src/devpoll.cpp b/src/devpoll.cpp index 897d2e91..d11ab16d 100644 --- a/src/devpoll.cpp +++ b/src/devpoll.cpp @@ -29,7 +29,7 @@ #include "precompiled.hpp" #include "devpoll.hpp" -#if defined ZMQ_USE_DEVPOLL +#if defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL #include #include diff --git a/src/devpoll.hpp b/src/devpoll.hpp index cc7dff36..ef84d808 100644 --- a/src/devpoll.hpp +++ b/src/devpoll.hpp @@ -32,7 +32,7 @@ // poller.hpp decides which polling mechanism to use. #include "poller.hpp" -#if defined ZMQ_USE_DEVPOLL +#if defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL #include diff --git a/src/epoll.cpp b/src/epoll.cpp index 7f3f9c1a..ef87dee5 100644 --- a/src/epoll.cpp +++ b/src/epoll.cpp @@ -29,7 +29,7 @@ #include "precompiled.hpp" #include "epoll.hpp" -#if defined ZMQ_USE_EPOLL +#if defined ZMQ_IOTHREAD_POLLER_USE_EPOLL #include #include diff --git a/src/epoll.hpp b/src/epoll.hpp index d320764f..b31504a0 100644 --- a/src/epoll.hpp +++ b/src/epoll.hpp @@ -32,7 +32,7 @@ // poller.hpp decides which polling mechanism to use. #include "poller.hpp" -#if defined ZMQ_USE_EPOLL +#if defined ZMQ_IOTHREAD_POLLER_USE_EPOLL #include #include diff --git a/src/kqueue.cpp b/src/kqueue.cpp index 93a53969..53d82ac4 100644 --- a/src/kqueue.cpp +++ b/src/kqueue.cpp @@ -29,7 +29,7 @@ #include "precompiled.hpp" #include "kqueue.hpp" -#if defined ZMQ_USE_KQUEUE +#if defined ZMQ_IOTHREAD_POLLER_USE_KQUEUE #include #include diff --git a/src/kqueue.hpp b/src/kqueue.hpp index e2d2f521..0b5a60a6 100644 --- a/src/kqueue.hpp +++ b/src/kqueue.hpp @@ -32,7 +32,7 @@ // poller.hpp decides which polling mechanism to use. #include "poller.hpp" -#if defined ZMQ_USE_KQUEUE +#if defined ZMQ_IOTHREAD_POLLER_USE_KQUEUE #include #include diff --git a/src/poll.cpp b/src/poll.cpp index 809685c6..67de088d 100644 --- a/src/poll.cpp +++ b/src/poll.cpp @@ -29,13 +29,11 @@ #include "precompiled.hpp" #include "poll.hpp" -#if defined ZMQ_USE_POLL +#if defined ZMQ_IOTHREAD_POLLER_USE_POLL #include -#if !defined ZMQ_HAVE_WINDOWS #include #include -#endif #include #include "poll.hpp" @@ -43,10 +41,6 @@ #include "config.hpp" #include "i_poll_events.hpp" -#ifdef ZMQ_HAVE_WINDOWS -typedef unsigned long nfds_t; -#endif - zmq::poll_t::poll_t (const zmq::thread_ctx_t &ctx_) : worker_poller_base_t (ctx_), retired (false) @@ -161,14 +155,10 @@ void zmq::poll_t::loop () // Wait for events. int rc = poll (&pollset[0], static_cast (pollset.size ()), timeout ? timeout : -1); -#ifdef ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); -#else if (rc == -1) { errno_assert (errno == EINTR); continue; } -#endif // If there are no events (i.e. it's a timeout) there's no point // in checking the pollset. diff --git a/src/poll.hpp b/src/poll.hpp index b766b344..da8bc931 100644 --- a/src/poll.hpp +++ b/src/poll.hpp @@ -32,11 +32,15 @@ // poller.hpp decides which polling mechanism to use. #include "poller.hpp" -#if defined ZMQ_USE_POLL +#if defined ZMQ_IOTHREAD_POLLER_USE_POLL -#if !defined ZMQ_HAVE_WINDOWS -#include +#if defined ZMQ_HAVE_WINDOWS +#error \ + "poll is broken on Windows for the purpose of the I/O thread poller, use select instead; "\ + "see https://github.com/zeromq/libzmq/issues/3107" #endif + +#include #include #include diff --git a/src/poller.hpp b/src/poller.hpp index 5b0d19df..ba9fbb17 100644 --- a/src/poller.hpp +++ b/src/poller.hpp @@ -30,35 +30,39 @@ #ifndef __ZMQ_POLLER_HPP_INCLUDED__ #define __ZMQ_POLLER_HPP_INCLUDED__ -#if defined ZMQ_USE_KQUEUE + defined ZMQ_USE_EPOLL + defined ZMQ_USE_DEVPOLL \ - + defined ZMQ_USE_POLLSET + defined ZMQ_USE_POLL + defined ZMQ_USE_SELECT \ +#if defined ZMQ_IOTHREAD_POLLER_USE_KQUEUE \ + + defined ZMQ_IOTHREAD_POLLER_USE_EPOLL \ + + defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL \ + + defined ZMQ_IOTHREAD_POLLER_USE_POLLSET \ + + defined ZMQ_IOTHREAD_POLLER_POLL \ + + defined ZMQ_IOTHREAD_POLLER_USE_SELECT \ > 1 -#error More than one of the ZMQ_USE_* macros defined +#error More than one of the ZMQ_IOTHREAD_POLLER_USE_* macros defined #endif -#if defined ZMQ_USE_KQUEUE +#if defined ZMQ_IOTHREAD_POLLER_USE_KQUEUE #include "kqueue.hpp" -#elif defined ZMQ_USE_EPOLL +#elif defined ZMQ_IOTHREAD_POLLER_USE_EPOLL #include "epoll.hpp" -#elif defined ZMQ_USE_DEVPOLL +#elif defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL #include "devpoll.hpp" -#elif defined ZMQ_USE_POLLSET +#elif defined ZMQ_IOTHREAD_POLLER_USE_POLLSET #include "pollset.hpp" -#elif defined ZMQ_USE_POLL +#elif defined ZMQ_IOTHREAD_POLLER_USE_POLL #include "poll.hpp" -#elif defined ZMQ_USE_SELECT +#elif defined ZMQ_IOTHREAD_POLLER_USE_SELECT #include "select.hpp" #elif defined ZMQ_HAVE_GNU -#define ZMQ_USE_POLL +#define ZMQ_IOTHREAD_POLLER_USE_POLL #include "poll.hpp" #else -#error None of the ZMQ_USE_* macros defined +#error None of the ZMQ_IOTHREAD_POLLER_USE_* macros defined #endif -#if defined ZMQ_USE_SELECT -#define ZMQ_POLL_BASED_ON_SELECT -#else -#define ZMQ_POLL_BASED_ON_POLL +#if (defined ZMQ_POLL_BASED_ON_SELECT + defined ZMQ_POLL_BASED_ON_POLL) > 1 +#error More than one of the ZMQ_POLL_BASED_ON_* macros defined +#elif (defined ZMQ_POLL_BASED_ON_SELECT + defined ZMQ_POLL_BASED_ON_POLL) == 0 +#error None of the ZMQ_POLL_BASED_ON_* macros defined #endif #endif diff --git a/src/pollset.cpp b/src/pollset.cpp index 9936dd91..1a1dee95 100644 --- a/src/pollset.cpp +++ b/src/pollset.cpp @@ -29,7 +29,7 @@ #include "precompiled.hpp" #include "pollset.hpp" -#if defined ZMQ_USE_POLLSET +#if defined ZMQ_IOTHREAD_POLLER_USE_POLLSET #include #include diff --git a/src/pollset.hpp b/src/pollset.hpp index d07b714b..bd99ad2d 100644 --- a/src/pollset.hpp +++ b/src/pollset.hpp @@ -32,7 +32,7 @@ // poller.hpp decides which polling mechanism to use. #include "poller.hpp" -#if defined ZMQ_USE_POLLSET +#if defined ZMQ_IOTHREAD_POLLER_USE_POLLSET #include #include diff --git a/src/select.cpp b/src/select.cpp index 7d0c1137..86bd8a80 100644 --- a/src/select.cpp +++ b/src/select.cpp @@ -29,7 +29,7 @@ #include "precompiled.hpp" #include "select.hpp" -#if defined ZMQ_USE_SELECT +#if defined ZMQ_IOTHREAD_POLLER_USE_SELECT #if defined ZMQ_HAVE_WINDOWS #elif defined ZMQ_HAVE_HPUX diff --git a/src/select.hpp b/src/select.hpp index 6553df66..7093c3d4 100644 --- a/src/select.hpp +++ b/src/select.hpp @@ -32,7 +32,7 @@ // poller.hpp decides which polling mechanism to use. #include "poller.hpp" -#if defined ZMQ_USE_SELECT +#if defined ZMQ_IOTHREAD_POLLER_USE_SELECT #include #include diff --git a/src/windows.hpp b/src/windows.hpp index 6c3839fd..824a256d 100644 --- a/src/windows.hpp +++ b/src/windows.hpp @@ -83,7 +83,7 @@ struct tcp_keepalive #include #endif -#if defined ZMQ_USE_POLL +#if defined ZMQ_IOTHREAD_POLLER_USE_POLL || defined ZMQ_POLL_BASED_ON_POLL static inline int poll (struct pollfd *pfd, unsigned long nfds, int timeout) { return WSAPoll (pfd, nfds, timeout);