Fix epoll_ctl not waking up epoll_wait
Co-authored-by: rduan@apache.org
This commit is contained in:
parent
52b75e3e06
commit
51eb43eb90
@ -312,9 +312,6 @@ impl EpollFile {
|
|||||||
|
|
||||||
let new_ep_inner = EpollEntryInner { event, flags };
|
let new_ep_inner = EpollEntryInner { event, flags };
|
||||||
let mut old_ep_inner = ep_entry.inner.lock().unwrap();
|
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;
|
*old_ep_inner = new_ep_inner;
|
||||||
drop(old_ep_inner);
|
drop(old_ep_inner);
|
||||||
|
|
||||||
|
@ -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 \
|
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 \
|
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 \
|
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
|
# Benchmarks: need to be compiled and run by bench-% target
|
||||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
||||||
|
|
||||||
|
5
test/epoll/Makefile
Normal file
5
test/epoll/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS := -lpthread
|
||||||
|
BIN_ARGS :=
|
177
test/epoll/main.c
Normal file
177
test/epoll/main.c
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <spawn.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#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));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user