Commit b2eaf870 authored by Pekka Paalanen's avatar Pekka Paalanen

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's avatarPekka Paalanen <ppaalanen@gmail.com>
parent 35d5053c
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include "wayland-server.h" #include "wayland-server.h"
#include "wayland-os.h"
struct wl_event_loop { struct wl_event_loop {
int epoll_fd; int epoll_fd;
...@@ -392,7 +393,7 @@ wl_event_loop_create(void) ...@@ -392,7 +393,7 @@ wl_event_loop_create(void)
if (loop == NULL) if (loop == NULL)
return NULL; return NULL;
loop->epoll_fd = epoll_create1(EPOLL_CLOEXEC); loop->epoll_fd = wl_os_epoll_create_cloexec();
if (loop->epoll_fd < 0) { if (loop->epoll_fd < 0) {
free(loop); free(loop);
return NULL; return NULL;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <sys/epoll.h>
#include "wayland-os.h" #include "wayland-os.h"
...@@ -124,3 +125,20 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) ...@@ -124,3 +125,20 @@ wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
return recvmsg_cloexec_fallback(sockfd, msg, 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);
}
...@@ -32,6 +32,9 @@ wl_os_dupfd_cloexec(int fd, long minfd); ...@@ -32,6 +32,9 @@ wl_os_dupfd_cloexec(int fd, long minfd);
ssize_t ssize_t
wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); 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. * The following are for wayland-os.c and the unit tests.
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <sys/epoll.h>
#include "../src/wayland-private.h" #include "../src/wayland-private.h"
#include "test-runner.h" #include "test-runner.h"
...@@ -50,6 +51,9 @@ static int wrapped_calls_fcntl; ...@@ -50,6 +51,9 @@ static int wrapped_calls_fcntl;
static ssize_t (*real_recvmsg)(int, struct msghdr *, int); static ssize_t (*real_recvmsg)(int, struct msghdr *, int);
static int wrapped_calls_recvmsg; static int wrapped_calls_recvmsg;
static int (*real_epoll_create1)(int);
static int wrapped_calls_epoll_create1;
static void static void
init_fallbacks(int do_fallbacks) init_fallbacks(int do_fallbacks)
{ {
...@@ -57,6 +61,7 @@ init_fallbacks(int do_fallbacks) ...@@ -57,6 +61,7 @@ init_fallbacks(int do_fallbacks)
real_socket = dlsym(RTLD_NEXT, "socket"); real_socket = dlsym(RTLD_NEXT, "socket");
real_fcntl = dlsym(RTLD_NEXT, "fcntl"); real_fcntl = dlsym(RTLD_NEXT, "fcntl");
real_recvmsg = dlsym(RTLD_NEXT, "recvmsg"); real_recvmsg = dlsym(RTLD_NEXT, "recvmsg");
real_epoll_create1 = dlsym(RTLD_NEXT, "epoll_create1");
} }
__attribute__ ((visibility("default"))) int __attribute__ ((visibility("default"))) int
...@@ -105,6 +110,20 @@ recvmsg(int sockfd, struct msghdr *msg, int flags) ...@@ -105,6 +110,20 @@ recvmsg(int sockfd, struct msghdr *msg, int flags)
return real_recvmsg(sockfd, msg, 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 static void
do_os_wrappers_socket_cloexec(int n) do_os_wrappers_socket_cloexec(int n)
{ {
...@@ -331,3 +350,35 @@ TEST(os_wrappers_recvmsg_cloexec_fallback) ...@@ -331,3 +350,35 @@ TEST(os_wrappers_recvmsg_cloexec_fallback)
init_fallbacks(1); init_fallbacks(1);
do_os_wrappers_recvmsg_cloexec(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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment