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