src/shared/util.c: add fallback for ppoll(), issue #129.

Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
This commit is contained in:
Anthony G. Basile 2016-03-21 10:58:20 -04:00
parent 1e521c3cf1
commit 0fe32c8006
3 changed files with 29 additions and 4 deletions

1
.gitignore vendored
View File

@ -10,6 +10,7 @@ Makefile.in
aclocal.m4
autom4te.cache
compile
config.*
configure
libtool

View File

@ -64,13 +64,17 @@ AC_C_INLINE
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_DECLS([getrandom, gettid, name_to_handle_at, accept4, mkostemp, strndupa], [], [], [[#include <sys/types.h>
#include <unistd.h>
AC_CHECK_DECLS([getrandom, gettid, name_to_handle_at, accept4, mkostemp, ppoll, strndupa], [], [],
[[#include <fcntl.h>
#include <linux/random.h>
#include <poll.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <linux/random.h>]])
#include <sys/types.h>
#include <unistd.h>]])
AC_CHECK_SIZEOF(pid_t)
AC_CHECK_SIZEOF(uid_t)

View File

@ -1091,6 +1091,21 @@ bool nulstr_contains(const char*nulstr, const char *needle) {
return false;
}
static inline int ppoll_fallback(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask) {
int ready, timeout;
sigset_t origmask;
timeout = (timeout_ts == NULL) ? -1 : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
/* This is racey, but what can we do without ppoll? */
sigprocmask(SIG_SETMASK, sigmask, &origmask);
ready = poll(fds, nfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);
return ready;
}
int fd_wait_for_event(int fd, int event, usec_t t) {
struct pollfd pollfd = {
@ -1101,7 +1116,12 @@ int fd_wait_for_event(int fd, int event, usec_t t) {
struct timespec ts;
int r;
#ifdef HAVE_DECL_PPOLL
r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
#else
/* Fallback path when ppoll() is unavailable */
r = ppoll_fallback(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
#endif
if (r < 0)
return -errno;