@@ -105,6 +105,7 @@ fn test_epoll_socketpair() {
105105
106106// This test first registers a file description with a flag that does not lead to notification,
107107// then EPOLL_CTL_MOD to add another flag that will lead to notification.
108+ // Also check that the new data value set via MOD is applied properly.
108109fn test_epoll_ctl_mod ( ) {
109110 // Create an epoll instance.
110111 let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -115,28 +116,49 @@ fn test_epoll_ctl_mod() {
115116 let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
116117 assert_eq ! ( res, 0 ) ;
117118
118- // Register fd[1] with EPOLLIN|EPOLLET.
119- let mut ev = libc:: epoll_event {
120- events : ( libc:: EPOLLIN | libc:: EPOLLET ) as _ ,
121- u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
122- } ;
119+ // Register fd[1] with EPOLLIN|EPOLLET, and data of "0".
120+ let mut ev = libc:: epoll_event { events : ( libc:: EPOLLIN | libc:: EPOLLET ) as _ , u64 : 0 } ;
123121 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
124122 assert_eq ! ( res, 0 ) ;
125123
126124 // Check result from epoll_wait. No notification would be returned.
127125 check_epoll_wait :: < 8 > ( epfd, & [ ] ) ;
128126
129- // Use EPOLL_CTL_MOD to change to EPOLLOUT flag.
130- let mut ev = libc:: epoll_event {
131- events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
132- u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
133- } ;
127+ // Use EPOLL_CTL_MOD to change to EPOLLOUT flag and data.
128+ let mut ev = libc:: epoll_event { events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ , u64 : 1 } ;
134129 let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_MOD , fds[ 1 ] , & mut ev) } ;
135130 assert_eq ! ( res, 0 ) ;
136131
137- // Check result from epoll_wait. EPOLLOUT notification is expected.
132+ // Check result from epoll_wait. EPOLLOUT notification and new data is expected.
138133 let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
139- let expected_value = u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ;
134+ let expected_value = 1 ;
135+ check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
136+
137+ // Write to fds[1] and read from fds[0] to make the notification ready again
138+ // (relying on there always being an event when the buffer gets emptied).
139+ let data = "abc" . as_bytes ( ) ;
140+ let res = unsafe { libc_utils:: write_all ( fds[ 1 ] , data. as_ptr ( ) . cast ( ) , data. len ( ) ) } ;
141+ assert_eq ! ( res, 3 ) ;
142+ let mut buf = [ 0u8 ; 3 ] ;
143+ let res = unsafe { libc_utils:: read_all ( fds[ 0 ] , buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) ) } ;
144+ assert_eq ! ( res, 3 ) ;
145+
146+ // Now that the event is already ready, change the "data" value.
147+ let mut ev = libc:: epoll_event { events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ , u64 : 2 } ;
148+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_MOD , fds[ 1 ] , & mut ev) } ;
149+ assert_eq ! ( res, 0 ) ;
150+
151+ // Receive event, with latest data value.
152+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
153+ let expected_value = 2 ;
154+ check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
155+
156+ // Do another update that changes nothing.
157+ let mut ev = libc:: epoll_event { events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ , u64 : 2 } ;
158+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_MOD , fds[ 1 ] , & mut ev) } ;
159+ assert_eq ! ( res, 0 ) ;
160+
161+ // This re-triggers the event, even if it's the same flags as before.
140162 check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
141163}
142164
0 commit comments