From 51eb43eb90f5325886a59dde4d364045eaf95dc5 Mon Sep 17 00:00:00 2001 From: "Hui, Chunyang" Date: Thu, 22 Sep 2022 05:55:43 +0000 Subject: [PATCH] Fix epoll_ctl not waking up epoll_wait Co-authored-by: rduan@apache.org --- .../net/io_multiplexing/epoll/epoll_file.rs | 3 - test/Makefile | 2 +- test/epoll/Makefile | 5 + test/epoll/main.c | 177 ++++++++++++++++++ 4 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 test/epoll/Makefile create mode 100644 test/epoll/main.c diff --git a/src/libos/src/net/io_multiplexing/epoll/epoll_file.rs b/src/libos/src/net/io_multiplexing/epoll/epoll_file.rs index 5b159337..6eee52da 100644 --- a/src/libos/src/net/io_multiplexing/epoll/epoll_file.rs +++ b/src/libos/src/net/io_multiplexing/epoll/epoll_file.rs @@ -312,9 +312,6 @@ impl EpollFile { let new_ep_inner = EpollEntryInner { event, flags }; let mut old_ep_inner = ep_entry.inner.lock().unwrap(); - if *old_ep_inner == new_ep_inner { - return Ok(()); - } *old_ep_inner = new_ep_inner; drop(old_ep_inner); diff --git a/test/Makefile b/test/Makefile index 68c99875..08720ddf 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,7 +22,7 @@ TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info rlimit \ server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group posix_flock \ ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \ - spawn_attribute exec statfs random umask pgrp vfork mount flock utimes shm + spawn_attribute exec statfs random umask pgrp vfork mount flock utimes shm epoll # Benchmarks: need to be compiled and run by bench-% target BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput diff --git a/test/epoll/Makefile b/test/epoll/Makefile new file mode 100644 index 00000000..5c1ee8c1 --- /dev/null +++ b/test/epoll/Makefile @@ -0,0 +1,5 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := +EXTRA_LINK_FLAGS := -lpthread +BIN_ARGS := diff --git a/test/epoll/main.c b/test/epoll/main.c new file mode 100644 index 00000000..58c9da33 --- /dev/null +++ b/test/epoll/main.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.h" + +// ============================================================================ +// Helper definition +// ============================================================================ + +#define MAXEVENTS 64 +#define TEST_DATA 678 + +struct thread_arg { + pthread_t tid; + int fd; + uint64_t data; +}; + +// ============================================================================ +// Helper functions +// ============================================================================ + +static void *thread_child(void *arg) { + struct thread_arg *child_arg = arg; + + printf("epoll_wait 1...\n"); + struct epoll_event events[MAXEVENTS] = {0}; + int nfds = epoll_wait(child_arg->fd, events, MAXEVENTS, -1); + if (nfds < 0) { + return (void *) -1; + } + printf("epoll_wait 1 success.\n"); + + sleep(1); + + printf("epoll_wait 2...\n"); + nfds = epoll_wait(child_arg->fd, events, MAXEVENTS, -1); + if (nfds < 0) { + return (void *) -1; + } + printf("epoll_wait 2 success.\n"); + return NULL; +} + +int create_child(struct thread_arg *arg) { + pthread_attr_t attr; + if (pthread_attr_init(&attr) != 0) { + THROW_ERROR("failed to initialize attribute"); + } + + if (pthread_create(&(arg->tid), &attr, &thread_child, arg) != 0) { + if (pthread_attr_destroy(&attr) != 0) { + THROW_ERROR("failed to destroy attr"); + } + THROW_ERROR("failed to create the thread"); + } + + if (pthread_attr_destroy(&attr) != 0) { + THROW_ERROR("failed to destroy attr"); + } + + return 0; +} + +// This test intends to test that the epoll_wait can be waken epoll_ctl +int test_epoll_ctl_main(int end_fd_1, int end_fd_2) { + uint64_t data = TEST_DATA; + struct thread_arg child_arg; + + int epfd = epoll_create1(0); + if (epfd == -1) { + THROW_ERROR("epoll_create failed"); + } + + // watch for end_fd_1 + struct epoll_event event; + event.data.fd = end_fd_1; + event.events = EPOLLIN | EPOLLET; + int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, end_fd_1, &event); + if (ret == -1) { + close(epfd); + THROW_ERROR("epoll_ctl add failed"); + } + + // write to end_fd_2 + int write_size = write(end_fd_2, &data, sizeof(data)); + if (write_size < 0) { + THROW_ERROR("failed to write an eventfd"); + } + + child_arg.data = 0; + child_arg.fd = epfd; + child_arg.tid = 0; + if (create_child(&child_arg) != 0) { + close(epfd); + THROW_ERROR("failed to create children"); + } + + // wait for child thread to start second time epoll_wait + sleep(3); + + printf("second time epoll ctl\n"); + ret = epoll_ctl(epfd, EPOLL_CTL_MOD, end_fd_1, &event); + if (ret == -1) { + close(epfd); + THROW_ERROR("epoll_ctl mod failed"); + } + + pthread_join(child_arg.tid, NULL); + close(epfd); + + return 0; +} + +// ============================================================================ +// Test cases for anonymous mmap +// ============================================================================ + +int test_epoll_ctl_uds() { + int sockets[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { + THROW_ERROR("opening stream socket pair"); + } + + int ret = test_epoll_ctl_main(sockets[0], sockets[1]); + close(sockets[0]); + close(sockets[1]); + + if (ret < 0) { + THROW_ERROR("epoll ctl test eventfd failure"); + } + + return 0; +} + +int test_epoll_ctl_eventfd() { + int event_fd = eventfd(0, EFD_NONBLOCK); + if (event_fd < 0) { + THROW_ERROR("failed to create an eventfd"); + } + + int ret = test_epoll_ctl_main(event_fd, event_fd); + close(event_fd); + + if (ret < 0) { + THROW_ERROR("epoll ctl test eventfd failure"); + } + return 0; +} + +// ============================================================================ +// Test suite main +// ============================================================================ + +static test_case_t test_cases[] = { + TEST_CASE(test_epoll_ctl_eventfd), + TEST_CASE(test_epoll_ctl_uds), +}; + +int main() { + return test_suite_run(test_cases, ARRAY_SIZE(test_cases)); +}