Skip to content

Instantly share code, notes, and snippets.

@bgaff
Created April 12, 2020 20:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bgaff/9a8fbbe8af79c0e18502430d416df77e to your computer and use it in GitHub Desktop.
Save bgaff/9a8fbbe8af79c0e18502430d416df77e to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <poll.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/userfaultfd.h>
struct test_data {
int uffd;
int timeout;
int poll_res;
int poll_errno;
int poll_revents;
};
static void *uffd_poll_thread(void *arg)
{
struct test_data* data = (struct test_data*)arg;
int res;
struct pollfd pfd;
pfd.fd = data->uffd;
pfd.events = POLLIN;
pfd.revents = 0;
/* Wait for an event or timeout */
res = poll(&pfd, 1, data->timeout);
data->poll_res = res;
data->poll_errno = errno;
data->poll_revents = pfd.revents;
return NULL;
}
static int test_userfaultfd_closing(int close_timeout, int poll_timeout)
{
struct test_data data;
struct uffdio_api uffdio_api;
pthread_t poll_thread;
int uffd = syscall(__NR_userfaultfd, O_NONBLOCK);
assert(uffd != -1);
uffdio_api.api = UFFD_API;
uffdio_api.features = 0;
assert(ioctl(uffd, UFFDIO_API, &uffdio_api) != -1);
data.uffd = uffd;
data.poll_revents = 0;
data.timeout = poll_timeout;
assert(pthread_create(&poll_thread, NULL,
uffd_poll_thread, (void *)&data) == 0);
/* Wait for the other thread to enter the poll */
usleep(1000*close_timeout);
assert(close(uffd) != -1);
assert(fcntl(uffd, F_GETFD) == -1 && errno == EBADF);
pthread_join(poll_thread, NULL);
/* We should be woken up about the fd being closed */
fprintf(stderr, "poll_res = %d, poll_revents = %X, poll_errno=%d\n",
data.poll_res, data.poll_revents, data.poll_errno);
assert(data.poll_res == 1);
assert(data.poll_revents & POLLERR);
return 0;
}
int main(int argc, char **argv)
{
if (argc < 3) {
return 1;
}
return test_userfaultfd_closing(atoi(argv[1]), atoi(argv[2]));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment