diff options
author | Pekka Paalanen <ppaalanen@gmail.com> | 2012-03-22 15:02:05 +0200 |
---|---|---|
committer | Pekka Paalanen <ppaalanen@gmail.com> | 2012-04-25 09:37:42 +0300 |
commit | b2eaf870cf8e8cb842ba29ea4718b596101252a6 (patch) | |
tree | ce24bd654adfd6ad7f4634f86cc074cef2b1924c | |
parent | 35d5053c622a2b1502b71230c7755a8005b36301 (diff) |
os: wrap epoll_create
Some system C libraries do not have epoll_create1() nor EPOLL_CLOEXEC,
provide a fallback.
Add tests for the wrapper.
Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
-rw-r--r-- | src/event-loop.c | 3 | ||||
-rw-r--r-- | src/wayland-os.c | 18 | ||||
-rw-r--r-- | src/wayland-os.h | 3 | ||||
-rw-r--r-- | tests/os-wrappers-test.c | 51 |
4 files changed, 74 insertions, 1 deletions
diff --git a/src/event-loop.c b/src/event-loop.c index 3bab3df..ee2eae5 100644 --- a/src/event-loop.c +++ b/src/event-loop.c @@ -34,6 +34,7 @@ #include <unistd.h> #include <assert.h> #include "wayland-server.h" +#include "wayland-os.h" struct wl_event_loop { int epoll_fd; @@ -392,7 +393,7 @@ wl_event_loop_create(void) if (loop == NULL) return NULL; - loop->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + loop->epoll_fd = wl_os_epoll_create_cloexec(); if (loop->epoll_fd < 0) { free(loop); return NULL; diff --git a/src/wayland-os.c b/src/wayland-os.c index eb53eec..a8756b6 100644 --- a/src/wayland-os.c +++ b/src/wayland-os.c @@ -25,6 +25,7 @@ #include <unistd.h> #include <fcntl.h> #include <errno.h> +#include <sys/epoll.h> #include "wayland-os.h" @@ -124,3 +125,20 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) return recvmsg_cloexec_fallback(sockfd, msg, flags); } + +int +wl_os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} diff --git a/src/wayland-os.h b/src/wayland-os.h index 43c317b..f6827f1 100644 --- a/src/wayland-os.h +++ b/src/wayland-os.h @@ -32,6 +32,9 @@ wl_os_dupfd_cloexec(int fd, long minfd); ssize_t wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); +int +wl_os_epoll_create_cloexec(void); + /* * The following are for wayland-os.c and the unit tests. diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c index 657f1fe..967eb83 100644 --- a/tests/os-wrappers-test.c +++ b/tests/os-wrappers-test.c @@ -34,6 +34,7 @@ #include <stdarg.h> #include <fcntl.h> #include <stdio.h> +#include <sys/epoll.h> #include "../src/wayland-private.h" #include "test-runner.h" @@ -50,6 +51,9 @@ static int wrapped_calls_fcntl; static ssize_t (*real_recvmsg)(int, struct msghdr *, int); static int wrapped_calls_recvmsg; +static int (*real_epoll_create1)(int); +static int wrapped_calls_epoll_create1; + static void init_fallbacks(int do_fallbacks) { @@ -57,6 +61,7 @@ init_fallbacks(int do_fallbacks) real_socket = dlsym(RTLD_NEXT, "socket"); real_fcntl = dlsym(RTLD_NEXT, "fcntl"); real_recvmsg = dlsym(RTLD_NEXT, "recvmsg"); + real_epoll_create1 = dlsym(RTLD_NEXT, "epoll_create1"); } __attribute__ ((visibility("default"))) int @@ -105,6 +110,20 @@ recvmsg(int sockfd, struct msghdr *msg, int flags) return real_recvmsg(sockfd, msg, flags); } +__attribute__ ((visibility("default"))) int +epoll_create1(int flags) +{ + wrapped_calls_epoll_create1++; + + if (fall_back) { + wrapped_calls_epoll_create1++; /* epoll_create() not wrapped */ + errno = EINVAL; + return -1; + } + + return real_epoll_create1(flags); +} + static void do_os_wrappers_socket_cloexec(int n) { @@ -331,3 +350,35 @@ TEST(os_wrappers_recvmsg_cloexec_fallback) init_fallbacks(1); do_os_wrappers_recvmsg_cloexec(1); } + +static void +do_os_wrappers_epoll_create_cloexec(int n) +{ + int fd; + int nr_fds; + + nr_fds = count_open_fds(); + + fd = wl_os_epoll_create_cloexec(); + assert(fd >= 0); + +#ifdef EPOLL_CLOEXEC + assert(wrapped_calls_epoll_create1 == n); +#else + printf("No epoll_create1.\n"); +#endif + + exec_fd_leak_check(nr_fds); +} + +TEST(os_wrappers_epoll_create_cloexec) +{ + init_fallbacks(0); + do_os_wrappers_epoll_create_cloexec(1); +} + +TEST(os_wrappers_epoll_create_cloexec_fallback) +{ + init_fallbacks(1); + do_os_wrappers_epoll_create_cloexec(2); +} |