From 1957fd0a84c674676e155665d8d26588f8e03309 Mon Sep 17 00:00:00 2001 From: Mehrdad Afshari Date: Tue, 16 Jan 2018 17:22:01 -0800 Subject: Enable epoll on Python manylinux1 The Python packages built for Linux and uploaded to PyPI are required to target a standardized platform specification dubbed `manylinux1`, which tries to cover a vast array of Linux distributions, thereby emulating a legacy lowest-common-denominator distribution, with an old `glibc` that does not support `epoll_create1`, but provides the `epoll_create` interface. While there are race condition risks associated with utilizing the latter interface and setting the `O_CLOEXEC` flag immediately on the file descriptor returned by `epoll_create`, the payoff is well worth the risks for our Python users, who currently end up falling back on `poll` polling engine when downloading our Linux binary packages. --- src/core/lib/iomgr/ev_epoll1_linux.cc | 26 ++++++++++++++++++++++++-- src/core/lib/iomgr/port.h | 5 ++++- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 1ab7e516de..6ec25d761f 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -84,11 +85,32 @@ typedef struct epoll_set { /* The global singleton epoll set */ static epoll_set g_epoll_set; +static int epoll_create_and_set_flag() { +#ifdef GRPC_LINUX_EPOLL_CREATE1 + int fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) { + return fd; + } + gpr_log(GPR_ERROR, "epoll_create1 unavailable"); + return -1; +#else + int fd = epoll_create(MAX_EPOLL_EVENTS); + if (fd < 0) { + gpr_log(GPR_ERROR, "epoll_create unavailable"); + return -1; + } + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == 0) { + return fd; + } + gpr_log(GPR_ERROR, "fcntl following epoll_create failed"); + return -1; +#endif +} + /* Must be called *only* once */ static bool epoll_set_init() { - g_epoll_set.epfd = epoll_create1(EPOLL_CLOEXEC); + g_epoll_set.epfd = epoll_create_and_set_flag(); if (g_epoll_set.epfd < 0) { - gpr_log(GPR_ERROR, "epoll unavailable"); return false; } diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 9fae8c0052..80867ee09f 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -67,8 +67,11 @@ #define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_TIMER_USE_GENERIC 1 #ifdef __GLIBC_PREREQ -#if __GLIBC_PREREQ(2, 9) +#if __GLIBC_PREREQ(2, 4) #define GRPC_LINUX_EPOLL 1 +#endif +#if __GLIBC_PREREQ(2, 9) +#define GRPC_LINUX_EPOLL_CREATE1 1 #define GRPC_LINUX_EVENTFD 1 #endif #if __GLIBC_PREREQ(2, 10) -- cgit v1.2.3