From f58e478e4354d4c32fdc10ea375788128404a96f Mon Sep 17 00:00:00 2001 From: Dmitrii Kuvaiskii Date: Tue, 9 Oct 2018 14:19:51 -0700 Subject: [PATCH] Fixes oscarlab/graphene#239 (shim_do_epoll_wait ignores user-supplied timeout) Better unit test to test shim_do_epoll_wait --- LibOS/shim/src/sys/shim_epoll.c | 5 +- .../test/regression/80_epoll_wait_timeout.py | 15 +++ .../shim/test/regression/epoll_wait_timeout.c | 126 ++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 LibOS/shim/test/regression/80_epoll_wait_timeout.py create mode 100644 LibOS/shim/test/regression/epoll_wait_timeout.c diff --git a/LibOS/shim/src/sys/shim_epoll.c b/LibOS/shim/src/sys/shim_epoll.c index 9de36f1f..1e59f140 100644 --- a/LibOS/shim/src/sys/shim_epoll.c +++ b/LibOS/shim/src/sys/shim_epoll.c @@ -321,8 +321,11 @@ retry: unlock(epoll_hdl->lock); + if (timeout < 0) + timeout = NO_TIMEOUT; + PAL_HANDLE polled = DkObjectsWaitAny(nread ? npals + 1 : npals, pal_handles, - nread ? NO_TIMEOUT : 0); + nread ? timeout : 0); lock(epoll_hdl->lock); diff --git a/LibOS/shim/test/regression/80_epoll_wait_timeout.py b/LibOS/shim/test/regression/80_epoll_wait_timeout.py new file mode 100644 index 00000000..fb6cdae3 --- /dev/null +++ b/LibOS/shim/test/regression/80_epoll_wait_timeout.py @@ -0,0 +1,15 @@ +#!/usr/bin/python + +import os, sys, mmap +from regression import Regression + +loader = sys.argv[1] + +regression = Regression(loader, "epoll_wait_timeout", None, 50000) + +regression.add_check(name="epoll_wait timeout", + args = ['8000'], + check=lambda res: "epoll_wait test passed" in res[0].out) + +rv = regression.run_checks() +if rv: sys.exit(rv) diff --git a/LibOS/shim/test/regression/epoll_wait_timeout.c b/LibOS/shim/test/regression/epoll_wait_timeout.c new file mode 100644 index 00000000..f0fe7e61 --- /dev/null +++ b/LibOS/shim/test/regression/epoll_wait_timeout.c @@ -0,0 +1,126 @@ +/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */ +/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* On success, a file descriptor for the new socket is returned. + * On error, -1 is returned. */ +static int create_and_bind (char *port) { + struct addrinfo hints; + struct addrinfo *result, *rp; + int s, sfd; + + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ + hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ + hints.ai_flags = AI_PASSIVE; /* All interfaces */ + + s = getaddrinfo (NULL, port, &hints, &result); + if (s != 0) { + fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s)); + return -1; + } + + for (rp = result; rp != NULL; rp = rp->ai_next) { + sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sfd == -1) + continue; + + s = bind (sfd, rp->ai_addr, rp->ai_addrlen); + if (s == 0) { + /* We managed to bind successfully! */ + break; + } + + close (sfd); + } + + if (rp == NULL) { + fprintf (stderr, "Could not bind\n"); + return -1; + } + + freeaddrinfo (result); + return sfd; +} + +/* On success, 0 is returned. On error, -1 is returned. */ +static int make_socket_non_blocking (int sfd) { + int flags, s; + + flags = fcntl (sfd, F_GETFL, 0); + if (flags == -1) { + perror ("fcntl"); + return -1; + } + + flags |= O_NONBLOCK; + s = fcntl (sfd, F_SETFL, flags); + if (s == -1) { + perror ("fcntl"); + return -1; + } + + return 0; +} + +#define MAXEVENTS 64 + +int main (int argc, char *argv[]) { + int sfd, s, n; + int efd; + struct epoll_event event; + struct epoll_event *events; + + if (argc != 2) { + perror("please specify port"); + return 1; + } + + sfd = create_and_bind(argv[1]); + if (sfd == -1) + return 1; + + s = make_socket_non_blocking(sfd); + if (s == -1) + return 1; + + s = listen(sfd, SOMAXCONN); + if (s == -1) { + perror ("listen"); + return 1; + } + + efd = epoll_create1(0); + if (efd == -1) { + perror ("epoll_create"); + return 1; + } + + event.data.fd = sfd; + event.events = EPOLLIN | EPOLLET; + s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event); + if (s == -1) { + perror ("epoll_ctl"); + return 1; + } + + events = calloc (MAXEVENTS, sizeof event); + + /* epoll_wait with 1 second timeout */ + n = epoll_wait (efd, events, MAXEVENTS, 1000); + + printf("epoll_wait test passed\n"); + free (events); + close (sfd); + return 0; +}