@@ -11,6 +11,7 @@ use std::thread::spawn;
11
11
fn main ( ) {
12
12
test_epoll_block_without_notification ( ) ;
13
13
test_epoll_block_then_unblock ( ) ;
14
+ test_notification_after_timeout ( ) ;
14
15
}
15
16
16
17
// Using `as` cast since `EPOLLET` wraps around
@@ -43,6 +44,8 @@ fn check_epoll_wait<const N: usize>(
43
44
assert_eq ! ( data, expected_event. 1 , "got wrong data" ) ;
44
45
}
45
46
}
47
+
48
+ // This test allows epoll_wait to block, then unblock without notification.
46
49
fn test_epoll_block_without_notification ( ) {
47
50
// Create an epoll instance.
48
51
let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -62,10 +65,11 @@ fn test_epoll_block_without_notification() {
62
65
let expected_value = fd as u64 ;
63
66
check_epoll_wait :: < 1 > ( epfd, & [ ( expected_event, expected_value) ] , 0 ) ;
64
67
65
- // epoll_wait before triggering notification so it will block then unblock .
68
+ // This epoll wait blocks, and timeout without notification .
66
69
check_epoll_wait :: < 1 > ( epfd, & [ ] , 5 ) ;
67
70
}
68
71
72
+ // This test triggers notification and unblocks the epoll_wait before timeout.
69
73
fn test_epoll_block_then_unblock ( ) {
70
74
// Create an epoll instance.
71
75
let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -98,3 +102,38 @@ fn test_epoll_block_then_unblock() {
98
102
check_epoll_wait :: < 1 > ( epfd, & [ ( expected_event, expected_value) ] , 10 ) ;
99
103
thread1. join ( ) . unwrap ( ) ;
100
104
}
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