mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-02 09:01:39 -05:00
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>
This commit is contained in:
parent
35d5053c62
commit
b2eaf870cf
4 changed files with 74 additions and 1 deletions
|
|
@ -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)
|
||||||
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 @@
|
||||||
#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)
|
||||||
|
|
||||||
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);
|
||||||
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 @@
|
||||||
#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;
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue