summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2016-03-21 10:58:20 -0400
committerAnthony G. Basile <blueness@gentoo.org>2016-03-21 10:58:31 -0400
commit0fe32c80063feb75cae18025174342a150e2ba5c (patch)
treeb5919585f559f2492c99792b8f99138fe0656905
parent1e521c3cf1687fd17bf8ceec1a7dadb5d003ed1a (diff)
src/shared/util.c: add fallback for ppoll(), issue #129.
Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
-rw-r--r--.gitignore1
-rw-r--r--configure.ac12
-rw-r--r--src/shared/util.c20
3 files changed, 29 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 9a1c2b4add..9e04dd33f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@ Makefile.in
aclocal.m4
autom4te.cache
+compile
config.*
configure
libtool
diff --git a/configure.ac b/configure.ac
index 19c4299ebf..19fcdd4ddc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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)
diff --git a/src/shared/util.c b/src/shared/util.c
index 88defdc4f2..3f6c1dcde4 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -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;