From 6cb51b22fa971e16554638ec3725b6126f284999 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Oct 2018 11:45:45 +0100 Subject: build: Never use poll() on Darwin family (macOS, etc.) or Interix Doing a runtime check in configure.ac (AC_RUN_IFELSE) has several disadvantages: * It doesn't work when cross-compiling. For example, if we build macOS binaries on a Linux system, we'd assume that poll() works, but in fact it won't. * It checks the build system capabilities, but that is not necessarily appropriate if (for example) a macOS 10.10 user builds binaries that could be used by macOS 10.12 or macOS 10.9 users. * It checks for one specific failure mode, but macOS seems to have a history of various implementation issues in poll(). * If we want it to work in CMake, we have to duplicate it in the CMake build system. None of these is a showstopper on its own, but the combination of all of them makes the current approach to avoiding the broken poll() on macOS look unreliable. libcurl, a widely-portable library making extensive use of sockets, specifically doesn't use poll() on Darwin (macOS, iOS, etc.) or on Interix; let's follow their example here. See also https://bugzilla.gnome.org/show_bug.cgi?id=302672 and https://daniel.haxx.se/blog/2016/10/11/poll-on-mac-10-12-is-broken/ for some relevant history. Signed-off-by: Simon McVittie Resolves: https://gitlab.freedesktop.org/dbus/dbus/issues/232 (cherry picked from commit 0414ea65ca8196e328da09c3a2324d7765fba8c4) --- configure.ac | 28 ---------------------------- dbus/dbus-sysdeps.h | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/configure.ac b/configure.ac index 09a12ab1..0a18ab62 100644 --- a/configure.ac +++ b/configure.ac @@ -630,34 +630,6 @@ fi AC_CHECK_HEADERS_ONCE([sys/prctl.h]) AC_CHECK_FUNCS_ONCE([prctl raise]) -#### Check for broken poll; taken from Glib's configure - -AC_MSG_CHECKING([for broken poll]) -AC_RUN_IFELSE([AC_LANG_SOURCE([[ - #include - #include - #include - #ifdef HAVE_SYS_POLL_H - #include - #endif - int main(void) { - struct pollfd fds[1]; - int fd; - fd = open("/dev/null", 1); - fds[0].fd = fd; - fds[0].events = POLLIN; - fds[0].revents = 0; - if (poll(fds, 1, 0) < 0 || (fds[0].revents & POLLNVAL) != 0) { - exit(1); /* Does not work for devices -- fail */ - } - exit(0); - }]])], - [broken_poll=no], - [broken_poll=yes - AC_DEFINE(BROKEN_POLL,1,[poll doesn't work on devices])], - [broken_poll="no (cross compiling)"]) -AC_MSG_RESULT($broken_poll) - AC_MSG_CHECKING(for dirfd) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 6892247f..ef786ecc 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -48,6 +48,32 @@ #include #include +#if !defined(BROKEN_POLL) && (defined(__APPLE__) || defined(__INTERIX)) + /* Following libcurl's example, we blacklist poll() on Darwin + * (macOS, iOS, etc.) and Interix due to a history of implementation + * issues. + * https://github.com/curl/curl/blob/master/m4/curl-functions.m4 + * + * On unspecified older macOS versions, poll() failed if given a + * device node to poll. + * + * On macOS < 10.9, poll() with nfds=0 failed instead of waiting for + * the timeout and then succeeding. + * + * On macOS >= 10.12, poll() with nfds=0 succeeded immediately + * instead of waiting for the timeout, resulting in busy-looping. + * + * On Interix, poll() apparently only works for files in /proc. + * + * The "legacy" build flavour in our CI machinery defines BROKEN_POLL + * on whatever platform is in use (normally Linux) to force use of the + * same select()-based poll() emulation that we use for macOS, Interix, + * and any platform that lacks a real poll(), so that we can test it + * more regularly. + */ +# define BROKEN_POLL +#endif + /* AIX sys/poll.h does #define events reqevents, and other * wonderousness, so must include sys/poll before declaring * DBusPollFD -- cgit v1.2.1