@@ -11,6 +11,7 @@ use std::thread::spawn;
1111fn main ( ) {
1212 test_epoll_block_without_notification ( ) ;
1313 test_epoll_block_then_unblock ( ) ;
14+ test_notification_after_timeout ( ) ;
1415}
1516
1617// Using `as` cast since `EPOLLET` wraps around
@@ -43,6 +44,8 @@ fn check_epoll_wait<const N: usize>(
4344 assert_eq ! ( data, expected_event. 1 , "got wrong data" ) ;
4445 }
4546}
47+
48+ // This test allows epoll_wait to block, then unblock without notification.
4649fn test_epoll_block_without_notification ( ) {
4750 // Create an epoll instance.
4851 let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -62,10 +65,11 @@ fn test_epoll_block_without_notification() {
6265 let expected_value = fd as u64 ;
6366 check_epoll_wait :: < 1 > ( epfd, & [ ( expected_event, expected_value) ] , 0 ) ;
6467
65- // epoll_wait before triggering notification so it will block then unblock .
68+ // This epoll wait blocks, and timeout without notification .
6669 check_epoll_wait :: < 1 > ( epfd, & [ ] , 5 ) ;
6770}
6871
72+ // This test triggers notification and unblocks the epoll_wait before timeout.
6973fn test_epoll_block_then_unblock ( ) {
7074 // Create an epoll instance.
7175 let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -98,3 +102,38 @@ fn test_epoll_block_then_unblock() {
98102 check_epoll_wait :: < 1 > ( epfd, & [ ( expected_event, expected_value) ] , 10 ) ;
99103 thread1. join ( ) . unwrap ( ) ;
100104}
105+
106+ // This test triggers a notification after epoll_wait times out.
107+ fn test_notification_after_timeout ( ) {
108+ // Create an epoll instance.
109+ let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
110+ assert_ne ! ( epfd, -1 ) ;
111+
112+ // Create a socketpair instance.
113+ let mut fds = [ -1 , -1 ] ;
114+ let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
115+ assert_eq ! ( res, 0 ) ;
116+
117+ // Register one side of the socketpair with epoll.
118+ let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : fds[ 0 ] as u64 } ;
119+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 0 ] , & mut ev) } ;
120+ assert_eq ! ( res, 0 ) ;
121+
122+ // epoll_wait to clear notification.
123+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
124+ let expected_value = fds[ 0 ] as u64 ;
125+ check_epoll_wait :: < 1 > ( epfd, & [ ( expected_event, expected_value) ] , 0 ) ;
126+
127+ // epoll_wait timeouts without notification.
128+ check_epoll_wait :: < 1 > ( epfd, & [ ] , 10 ) ;
129+
130+ // Trigger epoll notification after timeout.
131+ let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
132+ let res = unsafe { libc:: write ( fds[ 1 ] , data as * const libc:: c_void , 5 ) } ;
133+ assert_eq ! ( res, 5 ) ;
134+
135+ // Check the result of the notification.
136+ let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
137+ let expected_value = fds[ 0 ] as u64 ;
138+ check_epoll_wait :: < 1 > ( epfd, & [ ( expected_event, expected_value) ] , 10 ) ;
139+ }
0 commit comments