summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Hommel <wolfgang.hommel@unibw.de>2019-08-22 23:29:48 +0200
committerWolfgang Hommel <wolfgang.hommel@unibw.de>2019-08-22 23:29:48 +0200
commit5f033fe4867a9cf0c1a525c43f80e2ec30497490 (patch)
tree0fbbc96e0347b34f97b99b1007779cb6966ba8bf
parent52108dba7a79559712d3b2272fdf258c0baaa6dd (diff)
downloadlibfaketime-5f033fe4867a9cf0c1a525c43f80e2ec30497490.tar.gz
Intercept epoll_wait(), epoll_pwait(), and pselect() (#115)
-rw-r--r--NEWS3
-rw-r--r--src/libfaketime.c116
2 files changed, 119 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index eeaad30..26a68a9 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Since 0.9.7:
- Added FAKETIME_DONT_RESET environment variable to avoid
faketime resets when subprocesses are started (similar to
the old v0.9.6 behavior)
+ - Added FAKETIME_XRESET to avoid large clock jumps when
+ the 'x' modifier is used and changed during run-time
- Do not fake time during libfaketime initialization to
improve compatibility with memory allocation libraries that
use time-related functions themselves
@@ -16,6 +18,7 @@ Since 0.9.7:
not using the faketime wrapper
- Updated glibc compatibility settings for various platforms
- Support for clock_nanosleep() with realtime and monotonic clocks
+ - Support for epoll_wait(), epoll_pwait(), and pselect()
Since 0.9.6:
- Julien Gilli added an option to disable monotonic time faking
diff --git a/src/libfaketime.c b/src/libfaketime.c
index 714dcb0..f775810 100644
--- a/src/libfaketime.c
+++ b/src/libfaketime.c
@@ -30,6 +30,9 @@
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
+#ifdef __linux__
+#include <sys/epoll.h>
+#endif
#include <time.h>
#include <math.h>
#include <errno.h>
@@ -174,10 +177,21 @@ static unsigned int (*real_sleep) (unsigned int seconds);
static unsigned int (*real_alarm) (unsigned int seconds);
static int (*real_poll) (struct pollfd *, nfds_t, int);
static int (*real_ppoll) (struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
+#ifdef __linux__
+static int (*real_epoll_wait) (int epfd, struct epoll_event *events, int maxevents, int timeout);
+static int (*real_epoll_pwait) (int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask);
+#endif
static int (*real_select) (int nfds, fd_set *restrict readfds,
fd_set *restrict writefds,
fd_set *restrict errorfds,
struct timeval *restrict timeout);
+#ifdef __linux__
+static int (*real_pselect) (int nfds, fd_set *restrict readfds,
+ fd_set *restrict writefds,
+ fd_set *restrict errorfds,
+ const struct timespec *timeout,
+ const sigset_t *sigmask);
+#endif
static int (*real_sem_timedwait) (sem_t*, const struct timespec*);
#endif
#ifdef __APPLEOSX__
@@ -1290,6 +1304,60 @@ int ppoll(struct pollfd *fds, nfds_t nfds,
}
/*
+ * Faked epoll_wait()
+ */
+int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
+{
+ int ret, real_timeout;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_epoll_wait == NULL)
+ {
+ return -1;
+ }
+ if (user_rate_set && !dont_fake && timeout > 0)
+ {
+ real_timeout = (int) timeout * 1.0/user_rate;
+ }
+ else
+ {
+ real_timeout = timeout;
+ }
+ DONT_FAKE_TIME(ret = (*real_epoll_wait)(epfd, events, maxevents, real_timeout));
+ return ret;
+}
+
+/*
+ * Faked epoll_pwait()
+ */
+int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask)
+{
+ int ret, real_timeout;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_epoll_pwait == NULL)
+ {
+ return -1;
+ }
+ if (user_rate_set && !dont_fake && timeout > 0)
+ {
+ real_timeout = (int) timeout * 1.0/user_rate;
+ }
+ else
+ {
+ real_timeout = timeout;
+ }
+ DONT_FAKE_TIME(ret = (*real_epoll_pwait)(epfd, events, maxevents, real_timeout, sigmask));
+ return ret;
+}
+
+/*
* Faked poll()
*/
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
@@ -1355,6 +1423,47 @@ int select(int nfds, fd_set *readfds,
return ret;
}
+#ifdef __linux__
+/*
+ * Faked pselect()
+ */
+int pselect(int nfds, fd_set *readfds,
+ fd_set *writefds,
+ fd_set *errorfds,
+ const struct timespec *timeout,
+ const sigset_t *sigmask)
+{
+ int ret;
+ struct timespec timeout_real;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+
+ if (real_pselect == NULL)
+ {
+ return -1;
+ }
+
+ if (timeout != NULL)
+ {
+ if (user_rate_set && !dont_fake && (timeout->tv_sec > 0 || timeout->tv_nsec > 0))
+ {
+ timespecmul(timeout, 1.0 / user_rate, &timeout_real);
+ }
+ else
+ {
+ timeout_real.tv_sec = timeout->tv_sec;
+ timeout_real.tv_nsec = timeout->tv_nsec;
+ }
+ }
+
+ DONT_FAKE_TIME(ret = (*real_pselect)(nfds, readfds, writefds, errorfds, timeout == NULL ? timeout : &timeout_real, sigmask));
+ return ret;
+}
+#endif
+
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
{
int result;
@@ -2038,7 +2147,14 @@ static void ftpl_init(void)
real_alarm = dlsym(RTLD_NEXT, "alarm");
real_poll = dlsym(RTLD_NEXT, "poll");
real_ppoll = dlsym(RTLD_NEXT, "ppoll");
+#ifdef linux
+ real_epoll_wait = dlsym(RTLD_NEXT, "epoll_wait");
+ real_epoll_pwait = dlsym(RTLD_NEXT, "epoll_pwait");
+#endif
real_select = dlsym(RTLD_NEXT, "select");
+#ifdef __linux__
+ real_pselect = dlsym(RTLD_NEXT, "pselect");
+#endif
real_sem_timedwait = dlsym(RTLD_NEXT, "sem_timedwait");
#endif
#ifdef FAKE_INTERNAL_CALLS