@@ -14,6 +14,7 @@ fn main() {
1414 test_not_fully_closed_fd ( ) ;
1515 test_closed_fd ( ) ;
1616 test_two_epoll_instance ( ) ;
17+ test_no_notification_for_unregister_flag ( ) ;
1718 test_epoll_ctl_mod ( ) ;
1819 test_epoll_ctl_del ( ) ;
1920 test_pointer ( ) ;
@@ -68,7 +69,7 @@ fn test_epoll_socketpair() {
6869 u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
6970 } ;
7071 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
71- assert_ne ! ( res, - 1 ) ;
72+ assert_eq ! ( res, 0 ) ;
7273
7374 // Check result from epoll_wait.
7475 let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
@@ -99,6 +100,8 @@ fn test_epoll_socketpair() {
99100 check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
100101}
101102
103+ // This test first registers a file description with a flag that does not lead to notification,
104+ // then EPOLL_CTL_MOD to add another flag that will lead to notification.
102105fn test_epoll_ctl_mod ( ) {
103106 // Create an epoll instance.
104107 let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -109,37 +112,27 @@ fn test_epoll_ctl_mod() {
109112 let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
110113 assert_eq ! ( res, 0 ) ;
111114
112- // Write to fd[0].
113- let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
114- let res = unsafe { libc:: write ( fds[ 0 ] , data as * const libc:: c_void , 5 ) } ;
115- assert_eq ! ( res, 5 ) ;
116-
117- // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET.
118- // (Not using checked cast as EPOLLET wraps around.)
119- let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) } ;
115+ // Register fd[1] with EPOLLIN|EPOLLET.
116+ let mut ev = libc:: epoll_event {
117+ events : ( libc:: EPOLLIN | libc:: EPOLLET ) as _ ,
118+ u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
119+ } ;
120120 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
121- assert_ne ! ( res, - 1 ) ;
121+ assert_eq ! ( res, 0 ) ;
122122
123- // Check result from epoll_wait.
124- let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
125- let expected_value = u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ;
126- check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
123+ // Check result from epoll_wait. No notification would be returned.
124+ check_epoll_wait :: < 8 > ( epfd, & [ ] ) ;
127125
128- // Test EPOLLRDHUP .
126+ // Use EPOLL_CTL_MOD to change to EPOLLOUT flag .
129127 let mut ev = libc:: epoll_event {
130- events : ( libc:: EPOLLIN | libc :: EPOLLOUT | libc:: EPOLLET | libc :: EPOLLRDHUP ) as _ ,
128+ events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
131129 u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
132130 } ;
133131 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_MOD , fds[ 1 ] , & mut ev) } ;
134- assert_ne ! ( res, -1 ) ;
135-
136- // Close the other side of the socketpair to invoke EPOLLRDHUP.
137- let res = unsafe { libc:: close ( fds[ 0 ] ) } ;
138132 assert_eq ! ( res, 0 ) ;
139133
140- // Check result from epoll_wait.
141- let expected_event =
142- u32:: try_from ( libc:: EPOLLRDHUP | libc:: EPOLLIN | libc:: EPOLLOUT | libc:: EPOLLHUP ) . unwrap ( ) ;
134+ // Check result from epoll_wait. EPOLLOUT notification is expected.
135+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
143136 let expected_value = u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ;
144137 check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
145138}
@@ -162,10 +155,12 @@ fn test_epoll_ctl_del() {
162155 // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET
163156 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) } ;
164157 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
165- assert_ne ! ( res, - 1 ) ;
158+ assert_eq ! ( res, 0 ) ;
166159
167160 // Test EPOLL_CTL_DEL.
168- check_epoll_wait :: < 0 > ( epfd, & [ ] ) ;
161+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_DEL , fds[ 1 ] , & mut ev) } ;
162+ assert_eq ! ( res, 0 ) ;
163+ check_epoll_wait :: < 8 > ( epfd, & [ ] ) ;
169164}
170165
171166// This test is for one fd registered under two different epoll instance.
@@ -189,9 +184,9 @@ fn test_two_epoll_instance() {
189184 // Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET.
190185 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) } ;
191186 let res = unsafe { libc:: epoll_ctl ( epfd1, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
192- assert_ne ! ( res, - 1 ) ;
187+ assert_eq ! ( res, 0 ) ;
193188 let res = unsafe { libc:: epoll_ctl ( epfd2, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
194- assert_ne ! ( res, - 1 ) ;
189+ assert_eq ! ( res, 0 ) ;
195190
196191 // Notification should be received from both instance of epoll.
197192 let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
@@ -219,9 +214,9 @@ fn test_two_same_fd_in_same_epoll_instance() {
219214 // Register both fd to the same epoll instance.
220215 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : 5 as u64 } ;
221216 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
222- assert_ne ! ( res, - 1 ) ;
217+ assert_eq ! ( res, 0 ) ;
223218 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , newfd, & mut ev) } ;
224- assert_ne ! ( res, - 1 ) ;
219+ assert_eq ! ( res, 0 ) ;
225220
226221 // Write to the socketpair.
227222 let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
@@ -254,7 +249,7 @@ fn test_epoll_eventfd() {
254249 // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
255250 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fd) . unwrap ( ) } ;
256251 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
257- assert_ne ! ( res, - 1 ) ;
252+ assert_eq ! ( res, 0 ) ;
258253
259254 // Check result from epoll_wait.
260255 let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
@@ -277,7 +272,7 @@ fn test_pointer() {
277272 let mut ev =
278273 libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : data. expose_provenance ( ) as u64 } ;
279274 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
280- assert_ne ! ( res, - 1 ) ;
275+ assert_eq ! ( res, 0 ) ;
281276}
282277
283278// When read/write happened on one side of the socketpair, only the other side will be notified.
@@ -294,10 +289,10 @@ fn test_epoll_socketpair_both_sides() {
294289 // Register both fd to the same epoll instance.
295290 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : fds[ 0 ] as u64 } ;
296291 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 0 ] , & mut ev) } ;
297- assert_ne ! ( res, - 1 ) ;
292+ assert_eq ! ( res, 0 ) ;
298293 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : fds[ 1 ] as u64 } ;
299294 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
300- assert_ne ! ( res, - 1 ) ;
295+ assert_eq ! ( res, 0 ) ;
301296
302297 // Write to fds[1].
303298 let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
@@ -340,7 +335,7 @@ fn test_closed_fd() {
340335 // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
341336 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fd) . unwrap ( ) } ;
342337 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
343- assert_ne ! ( res, - 1 ) ;
338+ assert_eq ! ( res, 0 ) ;
344339
345340 // Write to the eventfd instance.
346341 let sized_8_data: [ u8 ; 8 ] = 1_u64 . to_ne_bytes ( ) ;
@@ -377,7 +372,7 @@ fn test_not_fully_closed_fd() {
377372 // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
378373 let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fd) . unwrap ( ) } ;
379374 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
380- assert_ne ! ( res, - 1 ) ;
375+ assert_eq ! ( res, 0 ) ;
381376
382377 // Close the original fd that being used to register with epoll.
383378 let res = unsafe { libc:: close ( fd) } ;
@@ -423,7 +418,7 @@ fn test_event_overwrite() {
423418 u64 : u64:: try_from ( fd) . unwrap ( ) ,
424419 } ;
425420 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
426- assert_ne ! ( res, - 1 ) ;
421+ assert_eq ! ( res, 0 ) ;
427422
428423 // Read from the eventfd instance.
429424 let mut buf: [ u8 ; 8 ] = [ 0 ; 8 ] ;
@@ -454,13 +449,13 @@ fn test_socketpair_read() {
454449 u64 : fds[ 0 ] as u64 ,
455450 } ;
456451 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 0 ] , & mut ev) } ;
457- assert_ne ! ( res, - 1 ) ;
452+ assert_eq ! ( res, 0 ) ;
458453 let mut ev = libc:: epoll_event {
459454 events : ( libc:: EPOLLIN | libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
460455 u64 : fds[ 1 ] as u64 ,
461456 } ;
462457 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
463- assert_ne ! ( res, - 1 ) ;
458+ assert_eq ! ( res, 0 ) ;
464459
465460 // Write 5 bytes to fds[1].
466461 let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
@@ -501,3 +496,35 @@ fn test_socketpair_read() {
501496 let expected_value = fds[ 1 ] as u64 ;
502497 check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
503498}
499+
500+ // This is to test whether flag that we don't register won't trigger notification.
501+ fn test_no_notification_for_unregister_flag ( ) {
502+ // Create an epoll instance.
503+ let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
504+ assert_ne ! ( epfd, -1 ) ;
505+
506+ // Create a socketpair instance.
507+ let mut fds = [ -1 , -1 ] ;
508+ let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
509+ assert_eq ! ( res, 0 ) ;
510+
511+ // Register fd[0] with EPOLLOUT|EPOLLET.
512+ let mut ev = libc:: epoll_event {
513+ events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
514+ u64 : u64:: try_from ( fds[ 0 ] ) . unwrap ( ) ,
515+ } ;
516+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
517+ assert_eq ! ( res, 0 ) ;
518+
519+ // Write to fd[1].
520+ let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
521+ let res: i32 =
522+ unsafe { libc:: write ( fds[ 1 ] , data as * const libc:: c_void , 5 ) . try_into ( ) . unwrap ( ) } ;
523+ assert_eq ! ( res, 5 ) ;
524+
525+ // Check result from epoll_wait. Since we didn't register EPOLLIN flag, the notification won't
526+ // contain EPOLLIN even though fds[0] is now readable.
527+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
528+ let expected_value = u64:: try_from ( fds[ 0 ] ) . unwrap ( ) ;
529+ check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
530+ }
0 commit comments