diff options
7 files changed, 748 insertions, 4 deletions
diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c index d5b3e127297..35dbf576f0e 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.c @@ -19,6 +19,7 @@ #include <pthread.h> #include <time.h> #include <stdarg.h> +#include <sys/resource.h> #include <libvcl-ldpreload/vcom_socket_wrapper.h> #include <libvcl-ldpreload/vcom.h> @@ -2940,24 +2941,319 @@ epoll_pwait (int __epfd, struct epoll_event *__events, This function is a cancellation point and therefore not marked with __THROW. */ + int vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) { + int rv = 0; + pid_t pid = getpid (); + + struct rlimit nofile_limit; + struct pollfd vcom_fds[MAX_POLL_NFDS_DEFAULT]; + nfds_t fds_idx = 0; + + /* actual set of file descriptors to be monitored */ + nfds_t libc_nfds = 0; + nfds_t vcom_nfds = 0; + + /* ready file descriptors + * + * number of structures which have nonzero revents fields + * in other words, descriptors with events or errors reported. + * */ + /* after call to libc_poll () */ + int rlibc_nfds = 0; + /* after call to vcom_socket_poll () */ + int rvcom_nfds = 0; + + + /* timeout value in units of timespec */ + struct timespec timeout_ts; + struct timespec start_time, now, end_time; + + + /* get start_time */ + rv = clock_gettime (CLOCK_MONOTONIC, &start_time); + if (rv == -1) + { + rv = -errno; + goto poll_done; + } + + /* set timeout_ts & end_time */ + if (__timeout >= 0) + { + /* set timeout_ts */ + timeout_ts.tv_sec = __timeout / MSEC_PER_SEC; + timeout_ts.tv_nsec = (__timeout % MSEC_PER_SEC) * NSEC_PER_MSEC; + set_normalized_timespec (&timeout_ts, + timeout_ts.tv_sec, timeout_ts.tv_nsec); + /* set end_time */ + if (__timeout) + { + end_time = timespec_add (start_time, timeout_ts); + } + else + { + end_time = start_time; + } + } + if (vcom_init () != 0) { - return -1; + rv = -1; + goto poll_done; } - return -EOPNOTSUPP; + /* validate __fds */ + if (!__fds) + { + rv = -EFAULT; + goto poll_done; + } + + /* validate __nfds */ + /*TBD: call getrlimit once when vcl-ldpreload library is init */ + rv = getrlimit (RLIMIT_NOFILE, &nofile_limit); + if (rv != 0) + { + rv = -errno; + goto poll_done; + } + if (__nfds >= nofile_limit.rlim_cur || __nfds < 0) + { + rv = -EINVAL; + goto poll_done; + } + + /* + * for the POC, it's fair to assume that nfds is less than 1024 + * */ + if (__nfds >= MAX_POLL_NFDS_DEFAULT) + { + rv = -EINVAL; + goto poll_done; + } + + /* set revents field (output parameter) + * to zero + * */ + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + __fds[fds_idx].revents = 0; + } + +#if 0 + /* set revents field (output parameter) + * to zero for user ignored fds + * */ + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* + * if negative fd, ignore events field + * and set output parameter (revents field) to zero */ + if (__fds[fds_idx].fd < 0) + { + __fds[fds_idx].revents = 0; + } + } +#endif + + /* + * 00. prepare __fds and vcom_fds for polling + * copy __fds to vcom_fds + * 01. negate all except libc fds in __fds, + * ignore user negated fds + * 02. negate all except vcom_fds in vocm fds, + * ignore user negated fds + * ignore fd 0 by setting it to negative number + * */ + memcpy (vcom_fds, __fds, sizeof (*__fds) * __nfds); + libc_nfds = 0; + vcom_nfds = 0; + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds */ + if (__fds[fds_idx].fd < 0) + { + continue; + } + + /* + * 00. ignore vcom fds in __fds + * 01. ignore libc fds in vcom_fds, + * ignore fd 0 by setting it to negative number. + * as fd 0 cannot be ignored. + */ + if (is_vcom_socket_fd (__fds[fds_idx].fd) || + is_vcom_epfd (__fds[fds_idx].fd)) + { + __fds[fds_idx].fd = -__fds[fds_idx].fd; + vcom_nfds++; + } + else + { + libc_nfds++; + /* ignore fd 0 by setting it to negative number */ + if (!vcom_fds[fds_idx].fd) + { + vcom_fds[fds_idx].fd = -1; + } + vcom_fds[fds_idx].fd = -vcom_fds[fds_idx].fd; + } + } + + /* + * polling loop + * + * poll on libc fds and vcom fds + * + * specifying a timeout of zero causes libc_poll() and + * vcom_socket_poll() to return immediately, even if no + * file descriptors are ready + * */ + do + { + rlibc_nfds = 0; + rvcom_nfds = 0; + + /* + * timeout parameter for libc_poll () set to zero + * to poll on libc fds + * */ + + /* poll on libc fds */ + if (libc_nfds) + { + /* + * a timeout of zero causes libc_poll() + * to return immediately + * */ + rlibc_nfds = libc_poll (__fds, __nfds, 0); + if (VCOM_DEBUG > 0) + fprintf (stderr, + "[%d] poll libc: " + "'%04d'='%08lu'\n", pid, rlibc_nfds, __nfds); + + if (rlibc_nfds < 0) + { + rv = -errno; + goto poll_done_update_nfds; + } + } + + /* + * timeout parameter for vcom_socket_poll () set to zero + * to poll on vcom fds + * */ + + /* poll on vcom fds */ + if (vcom_nfds) + { + /* + * a timeout of zero causes vcom_socket_poll() + * to return immediately + * */ + rvcom_nfds = vcom_socket_poll (vcom_fds, __nfds, 0); + if (VCOM_DEBUG > 0) + fprintf (stderr, + "[%d] poll vcom: " + "'%04d'='%08lu'\n", pid, rvcom_nfds, __nfds); + if (rvcom_nfds < 0) + { + rv = rvcom_nfds; + goto poll_done_update_nfds; + } + } + + /* check if any file descriptors changed status */ + if ((libc_nfds && rlibc_nfds > 0) || (vcom_nfds && rvcom_nfds > 0)) + { + /* something interesting happened */ + rv = rlibc_nfds + rvcom_nfds; + goto poll_done_update_nfds; + } + + rv = clock_gettime (CLOCK_MONOTONIC, &now); + if (rv == -1) + { + rv = -errno; + goto poll_done_update_nfds; + } + } + + /* block indefinitely || timeout elapsed */ + while ((__timeout < 0) || timespec_compare (&now, &end_time) < 0); + + /* timeout expired before anything interesting happened */ + rv = 0; + +poll_done_update_nfds: + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds in vcom_fds + * 00. user negated fds + * 01. libc fds + * */ + if (vcom_fds[fds_idx].fd < 0) + { + continue; + } + + /* from here on handle positive vcom fds */ + /* + * restore vcom fds to positive number in __fds + * and update revents in __fds with the events + * that actually occurred in vcom fds + * */ + __fds[fds_idx].fd = -__fds[fds_idx].fd; + if (rvcom_nfds) + { + __fds[fds_idx].revents = vcom_fds[fds_idx].revents; + } + } + +poll_done: + if (VCOM_DEBUG > 0) + fprintf (stderr, "[%d] vpoll: " "'%04d'='%08lu'\n", pid, rv, __nfds); + return rv; } +/* + * 00. The field __fds[i].fd contains a file descriptor for an + * open file. + * If this field is negative, then the corresponding + * events field is ignored and the revents field returns zero. + * The field __fds[i].events is an input parameter. + * The field __fds[i].revents is an output parameter. + * 01. Specifying a negative value in timeout + * means an infinite timeout. + * Specifying a timeout of zero causes poll() to return + * immediately, even if no file descriptors are ready. + * + * NOTE: observed __nfds is less than 128 from kubecon strace files + */ + + int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) { int rv = 0; + pid_t pid = getpid (); - errno = EOPNOTSUPP; - rv = -1; + + if (VCOM_DEBUG > 0) + fprintf (stderr, "[%d] poll1: " "'%04d'='%08lu, %d, 0x%x'\n", + pid, rv, __nfds, __fds[0].fd, __fds[0].events); + rv = vcom_poll (__fds, __nfds, __timeout); + if (VCOM_DEBUG > 0) + fprintf (stderr, "[%d] poll2: " "'%04d'='%08lu, %d, 0x%x'\n", + pid, rv, __nfds, __fds[0].fd, __fds[0].revents); + if (rv < 0) + { + errno = -rv; + return -1; + } return rv; } diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h index bedeef807ac..5871b5205b0 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom.h @@ -178,6 +178,12 @@ extern int vcom_epoll_pwait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout, const __sigset_t * __ss); +/* + * NOTE: observed __nfds is less than 128 from kubecon strace files + * for the POC, it's fair to assume that nfds is less than 1024. + * TBD: make it thread safe and design to scale. + * */ +#define MAX_POLL_NFDS_DEFAULT 1024 extern int vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); #ifdef __USE_GNU diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_glibc_socket.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_glibc_socket.h index 0f1b1743faa..4eb60fb65c7 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_glibc_socket.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_glibc_socket.h @@ -23,6 +23,8 @@ #include <fcntl.h> #include <sys/epoll.h> + +#include <signal.h> #include <poll.h> /* diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c index 96108afe0f7..4a5f28574ed 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.c @@ -2793,6 +2793,395 @@ out: return rv; } +static inline void +vcom_pollfds_2_selectfds ( + /* src */ + struct pollfd *__fds, nfds_t __nfds, + /* dest */ + int vcom_nfds, + fd_set * __restrict vcom_readfds, + fd_set * __restrict vcom_writefds, + fd_set * __restrict vcom_exceptfds) +{ + nfds_t fds_idx = 0; + + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds */ + if (__fds[fds_idx].fd < 0) + { + continue; + } + + /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */ + FD_SET (__fds[fds_idx].fd, vcom_exceptfds); + + /* requested events */ + if (__fds[fds_idx].events) + { + if (__fds[fds_idx].events & POLLIN) + { + FD_SET (__fds[fds_idx].fd, vcom_readfds); + } + if (__fds[fds_idx].events & POLLPRI) + { + FD_SET (__fds[fds_idx].fd, vcom_readfds); + } + if (__fds[fds_idx].events & POLLOUT) + { + FD_SET (__fds[fds_idx].fd, vcom_writefds); + } +#if defined __USE_XOPEN || defined __USE_XOPEN2K8 + if (__fds[fds_idx].events & POLLRDNORM) + { + FD_SET (__fds[fds_idx].fd, vcom_readfds); + } + if (__fds[fds_idx].events & POLLRDBAND) + { + FD_SET (__fds[fds_idx].fd, vcom_readfds); + } + if (__fds[fds_idx].events & POLLWRNORM) + { + FD_SET (__fds[fds_idx].fd, vcom_writefds); + } + if (__fds[fds_idx].events & POLLWRBAND) + { + FD_SET (__fds[fds_idx].fd, vcom_writefds); + } +#endif + } + } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */ +} + +static inline void +vcom_selectfds_2_pollfds ( + /* dest */ + struct pollfd *__fds, nfds_t __nfds, int *nfd, + /* src */ + int vcom_nfds, + fd_set * __restrict vcom_readfds, + fd_set * __restrict vcom_writefds, + fd_set * __restrict vcom_exceptfds) +{ + nfds_t fds_idx = 0; + + + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds */ + if (__fds[fds_idx].fd < 0) + { + __fds[fds_idx].revents = 0; + } + + /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */ + if (FD_ISSET (__fds[fds_idx].fd, vcom_exceptfds)) + { + /* + * TBD: for now any select exception + * is flagged as POLLERR + * */ + __fds[fds_idx].revents |= POLLERR; + } + + /* requested events */ + if (__fds[fds_idx].events & POLLIN) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) + { + __fds[fds_idx].revents |= POLLIN; + } + } + if (__fds[fds_idx].events & POLLPRI) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) + { + __fds[fds_idx].revents |= POLLIN; + } + } + if (__fds[fds_idx].events & POLLOUT) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds)) + { + __fds[fds_idx].revents |= POLLOUT; + } + } +#if defined __USE_XOPEN || defined __USE_XOPEN2K8 + if (__fds[fds_idx].events & POLLRDNORM) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) + { + __fds[fds_idx].revents |= POLLRDNORM; + } + } + if (__fds[fds_idx].events & POLLRDBAND) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) + { + __fds[fds_idx].revents |= POLLRDBAND; + } + } + if (__fds[fds_idx].events & POLLWRNORM) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds)) + { + __fds[fds_idx].revents |= POLLWRNORM; + } + } + if (__fds[fds_idx].events & POLLWRBAND) + { + if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds)) + { + __fds[fds_idx].revents |= POLLWRBAND; + } + } +#endif + } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */ + + /* + * nfd: + * the number of structures which have nonzero revents fields + * (in other words, those descriptors with events or + * errors reported) + * */ + *nfd = 0; + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds */ + if (__fds[fds_idx].fd < 0) + { + continue; + } + + if (__fds[fds_idx].revents) + { + (*nfd)++; + } + } +} + +/* + * PRE: parameters are validated, + * vcom_socket_poll is always called with __timeout set to zero + * hence returns immediately + * + * ACTION: handle non negative validated vcom fds and ignore rest + */ + +/* + * implements vcom_socket_poll () interface + * + * internally uses vcom_socket_select () + * to realize the behavior + * */ +int +vcom_socket_poll_select_impl (struct pollfd *__fds, nfds_t __nfds, + int __timeout) +{ + int rv; + pid_t pid = getpid (); + + nfds_t fds_idx = 0; + int nfd = 0; + + /* vcom */ + int vcom_nfds = 0; + fd_set vcom_readfds; + fd_set vcom_writefds; + fd_set vcom_exceptfds; + int vcom_nfd = -1; + /* invalid max_vcom_fd is -1 */ + int max_vcom_fd = -1; + + /* __timeout is zero to get ready events and return immediately */ + struct timeval tv = {.tv_sec = 0,.tv_usec = 0 }; + + /* validate __nfds from select perspective */ + if (__nfds < 0 || __nfds > FD_SETSIZE) + { + rv = -EINVAL; + goto poll_done; + } + + /* zero vcom fd sets */ + /* + * V vcom fd set + */ +#define _(V) \ + FD_ZERO ((V)) + + _(&vcom_readfds); + _(&vcom_writefds); + _(&vcom_exceptfds); +#undef _ + + vcom_nfds = 0; + vcom_nfd = -1; + + + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds */ + if (__fds[fds_idx].fd < 0) + { + continue; + } + + /* non negative validated vcom fds */ + if (__fds[fds_idx].fd > FD_SETSIZE) + { + rv = -EINVAL; + goto poll_done; + } + + /* max_vcom_fd and vcom_nfd */ + if (__fds[fds_idx].fd > max_vcom_fd) + { + /* requested events */ + if (__fds[fds_idx].events) + { + max_vcom_fd = __fds[fds_idx].fd; + } + } + ++vcom_nfd; + } + + vcom_nfds = max_vcom_fd != -1 ? max_vcom_fd + 1 : 0; + + if (!vcom_nfds) + { + rv = vcom_nfds; + goto poll_done; + } + + vcom_pollfds_2_selectfds ( + /* src */ + __fds, __nfds, + /* dest */ + vcom_nfds, + &vcom_readfds, &vcom_writefds, &vcom_exceptfds); + + /* select on vcom fds */ + vcom_nfd = vcom_socket_select (vcom_nfds, + &vcom_readfds, + &vcom_writefds, &vcom_exceptfds, &tv); + if (VCOM_DEBUG > 0) + fprintf (stderr, + "[%d] vcom_socket_select: " + "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds); + + if (vcom_nfd < 0) + { + rv = vcom_nfd; + goto poll_done; + } + + vcom_selectfds_2_pollfds ( + /* dest */ + __fds, __nfds, &nfd, + /* src */ + vcom_nfds, + &vcom_readfds, &vcom_writefds, &vcom_exceptfds); + + rv = nfd; + +poll_done: + return rv; +} + +/* + * TBD: remove this static function once vppcom + * has an implementation in place + * + * ACTION: + */ +static int +vppcom_poll (struct pollfd *__fds, nfds_t __nfds, double time_to_wait) +{ + return -EOPNOTSUPP; +} + +int +vcom_socket_poll_vppcom_impl (struct pollfd *__fds, nfds_t __nfds, + int __timeout) +{ + nfds_t fds_idx = 0; + + /* in seconds eg. 3.123456789 seconds */ + double time_to_wait = (double) 0; + + i32 sid; + i32 vep_idx; + + /* replace vcom fd with session idx */ + for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + { + /* ignore negative fds */ + if (__fds[fds_idx].fd < 0) + { + continue; + } + + /* non negative validated vcom fds */ + sid = vcom_socket_get_sid (__fds[fds_idx].fd); + if (sid != INVALID_SESSION_ID) + { + __fds[fds_idx].fd = sid; + } + else + { + /* get vep_idx */ + vep_idx = vcom_socket_get_vep_idx (__fds[fds_idx].fd); + if (vep_idx != INVALID_VEP_IDX) + { + __fds[fds_idx].fd = vep_idx; + } + else + { + return -EBADF; + } + } + } + + /* validate __timeout */ + if (__timeout > 0) + { + time_to_wait = (double) __timeout / (double) 1000; + } + else if (__timeout == 0) + { + time_to_wait = (double) 0; + } + else if (__timeout < 0) + { + time_to_wait = ~0; + } + else + { + return -EBADF; + } + + return vppcom_poll (__fds, __nfds, time_to_wait); +} + +int +vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) +{ + /* select an implementation */ + + /* return vcom_socket_poll_vppcom_impl (__fds, __nfds, __timeout); */ + return vcom_socket_poll_select_impl (__fds, __nfds, __timeout); +} + +#ifdef __USE_GNU +int +vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss) +{ + return -EOPNOTSUPP; +} +#endif + int vcom_socket_main_init (void) { diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h index ef57646966b..9dc18f58af2 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket.h @@ -448,6 +448,17 @@ vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout, const __sigset_t * __ss); +/* + * handle only vcom fds + */ +int vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); + +#ifdef __USE_GNU +int +vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss); +#endif + #endif /* included_vcom_socket_h */ /* diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c index 087cd6bbc52..9b961af6bad 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.c @@ -263,6 +263,15 @@ typedef int (*__libc_epoll_pwait) (int __epfd, struct epoll_event * __events, int __maxevents, int __timeout, const __sigset_t * __ss); +typedef int (*__libc_poll) (struct pollfd * __fds, nfds_t __nfds, + int __timeout); + +#ifdef __USE_GNU +typedef int (*__libc_ppoll) (struct pollfd * __fds, nfds_t __nfds, + const struct timespec * __timeout, + const __sigset_t * __ss); +#endif + #define SWRAP_SYMBOL_ENTRY(i) \ union { \ @@ -334,6 +343,10 @@ struct swrap_libc_symbols SWRAP_SYMBOL_ENTRY (epoll_ctl); SWRAP_SYMBOL_ENTRY (epoll_wait); SWRAP_SYMBOL_ENTRY (epoll_pwait); + SWRAP_SYMBOL_ENTRY (poll); +#ifdef __USE_GNU + SWRAP_SYMBOL_ENTRY (ppoll); +#endif }; struct swrap @@ -811,6 +824,25 @@ libc_epoll_pwait (int __epfd, struct epoll_event *__events, __ss); } +int +libc_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) +{ + swrap_bind_symbol_libc (poll); + + return swrap.libc.symbols._libc_poll.f (__fds, __nfds, __timeout); +} + +#ifdef __USE_GNU +int +libc_ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss) +{ + swrap_bind_symbol_libc (ppoll); + + return swrap.libc.symbols._libc_ppoll.f (__fds, __nfds, __timeout, __ss); +} +#endif + static void swrap_thread_prepare (void) { diff --git a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h index 49ee7eee9e6..9e85ecf2b6c 100644 --- a/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h +++ b/extras/vcl-ldpreload/src/libvcl-ldpreload/vcom_socket_wrapper.h @@ -63,6 +63,7 @@ #include <sys/ioctl.h> #include <sys/select.h> #include <sys/epoll.h> +#include <poll.h> #include <sys/uio.h> #include <stdlib.h> @@ -212,6 +213,13 @@ int libc_epoll_pwait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout, const __sigset_t * __ss); +int libc_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); + +#ifdef __USE_GNU +int libc_ppoll (struct pollfd *__fds, nfds_t __nfds, + const struct timespec *__timeout, const __sigset_t * __ss); +#endif + void swrap_constructor (void); void swrap_destructor (void); |