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 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); | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										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