@@ -16,6 +16,7 @@ fn main() {
1616 test_epoll_ctl_del ( ) ;
1717 test_pointer ( ) ;
1818 test_two_same_fd_in_same_epoll_instance ( ) ;
19+ test_socketpair_read ( ) ;
1920}
2021
2122fn check_epoll_wait < const N : usize > (
@@ -339,16 +340,18 @@ fn test_epoll_socketpair_special_case() {
339340 vec![ ( expected_event1, expected_value1) , ( expected_event0, expected_value0) ]
340341 ) ) ;
341342
342- // Read from fds[0]
343+ // Read from fds[0].
343344 let mut buf: [ u8 ; 5 ] = [ 0 ; 5 ] ;
344345 res = unsafe {
345346 libc:: read ( fds[ 0 ] , buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
346347 } ;
347348 assert_eq ! ( res, 5 ) ;
348349 assert_eq ! ( buf, "abcde" . as_bytes( ) ) ;
349350
350- // No notification should be returned.
351- assert ! ( check_epoll_wait:: <8 >( epfd, vec![ ] ) ) ;
351+ // Notification should be provided for fds[1].
352+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
353+ let expected_value = fds[ 1 ] as u64 ;
354+ assert ! ( check_epoll_wait:: <8 >( epfd, vec![ ( expected_event, expected_value) ] ) ) ;
352355}
353356
354357// When file description is fully closed, epoll_wait should not provide any notification for
@@ -481,3 +484,64 @@ fn test_event_overwrite() {
481484 let expected_value = u64:: try_from ( fd) . unwrap ( ) ;
482485 assert ! ( check_epoll_wait:: <8 >( epfd, vec![ ( expected_event, expected_value) ] ) ) ;
483486}
487+
488+ // read in socketpair will only provide epoll notification if it emptied the buffer.
489+ fn test_socketpair_read ( ) {
490+ // Create an epoll instance.
491+ let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
492+ assert_ne ! ( epfd, -1 ) ;
493+
494+ // Create a socketpair instance.
495+ let mut fds = [ -1 , -1 ] ;
496+ let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
497+ assert_eq ! ( res, 0 ) ;
498+
499+ // Register both fd to the same epoll instance.
500+ let epollet = libc:: EPOLLET as u32 ;
501+ let flags = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) | epollet;
502+ let mut ev = libc:: epoll_event { events : u32:: try_from ( flags) . unwrap ( ) , u64 : fds[ 0 ] as u64 } ;
503+ let mut res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 0 ] , & mut ev) } ;
504+ assert_ne ! ( res, -1 ) ;
505+ let mut ev = libc:: epoll_event { events : u32:: try_from ( flags) . unwrap ( ) , u64 : fds[ 1 ] as u64 } ;
506+ res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
507+ assert_ne ! ( res, -1 ) ;
508+
509+ // Write 5 bytes to fds[1].
510+ let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
511+ res = unsafe { libc:: write ( fds[ 1 ] , data as * const libc:: c_void , 5 ) . try_into ( ) . unwrap ( ) } ;
512+ assert_eq ! ( res, 5 ) ;
513+
514+ //Two notification should be received.
515+ let expected_event0 = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
516+ let expected_value0 = fds[ 0 ] as u64 ;
517+ let expected_event1 = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
518+ let expected_value1 = fds[ 1 ] as u64 ;
519+ assert ! ( check_epoll_wait:: <8 >(
520+ epfd,
521+ vec![ ( expected_event1, expected_value1) , ( expected_event0, expected_value0) ]
522+ ) ) ;
523+
524+ // Read 3 bytes from fds[0].
525+ let mut buf: [ u8 ; 3 ] = [ 0 ; 3 ] ;
526+ res = unsafe {
527+ libc:: read ( fds[ 0 ] , buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
528+ } ;
529+ assert_eq ! ( res, 3 ) ;
530+ assert_eq ! ( buf, "abc" . as_bytes( ) ) ;
531+
532+ // No notification should be provided.
533+ assert ! ( check_epoll_wait:: <8 >( epfd, vec![ ] ) ) ;
534+
535+ // Read until the buffer is empty.
536+ let mut buf: [ u8 ; 2 ] = [ 0 ; 2 ] ;
537+ res = unsafe {
538+ libc:: read ( fds[ 0 ] , buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
539+ } ;
540+ assert_eq ! ( res, 2 ) ;
541+ assert_eq ! ( buf, "de" . as_bytes( ) ) ;
542+
543+ // Notification should be provided.
544+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
545+ let expected_value = fds[ 1 ] as u64 ;
546+ assert ! ( check_epoll_wait:: <8 >( epfd, vec![ ( expected_event, expected_value) ] ) ) ;
547+ }
0 commit comments