@@ -758,12 +758,9 @@ mod sys {
758
758
use std:: convert:: TryInto ;
759
759
use std:: io;
760
760
use std:: os:: unix:: io:: RawFd ;
761
+ use std:: ptr;
761
762
use std:: time:: Duration ;
762
763
763
- use crate :: sys:: epoll:: {
764
- epoll_create1, epoll_ctl, epoll_wait, EpollEvent , EpollFlags , EpollOp ,
765
- } ;
766
-
767
764
macro_rules! syscall {
768
765
( $fn: ident $args: tt) => { {
769
766
let res = unsafe { libc:: $fn $args } ;
@@ -781,7 +778,42 @@ mod sys {
781
778
}
782
779
impl Reactor {
783
780
pub fn new ( ) -> io:: Result < Reactor > {
784
- let epoll_fd = epoll_create1 ( ) ?;
781
+ // According to libuv, `EPOLL_CLOEXEC` is not defined on Android API < 21.
782
+ // But `EPOLL_CLOEXEC` is an alias for `O_CLOEXEC` on that platform, so we use it instead.
783
+ #[ cfg( target_os = "android" ) ]
784
+ const CLOEXEC : libc:: c_int = libc:: O_CLOEXEC ;
785
+ #[ cfg( not( target_os = "android" ) ) ]
786
+ const CLOEXEC : libc:: c_int = libc:: EPOLL_CLOEXEC ;
787
+
788
+ let epoll_fd = unsafe {
789
+ // Check if the `epoll_create1` symbol is available on this platform.
790
+ let ptr = libc:: dlsym (
791
+ libc:: RTLD_DEFAULT ,
792
+ "epoll_create1\0 " . as_ptr ( ) as * const libc:: c_char ,
793
+ ) ;
794
+
795
+ if ptr. is_null ( ) {
796
+ // If not, use `epoll_create` and manually set `CLOEXEC`.
797
+ let fd = match libc:: epoll_create ( 1024 ) {
798
+ -1 => return Err ( io:: Error :: last_os_error ( ) ) ,
799
+ fd => fd,
800
+ } ;
801
+ let flags = libc:: fcntl ( fd, libc:: F_GETFD ) ;
802
+ libc:: fcntl ( fd, libc:: F_SETFD , flags | libc:: FD_CLOEXEC ) ;
803
+ fd
804
+ } else {
805
+ // Use `epoll_create1` with `CLOEXEC`.
806
+ let epoll_create1 = std:: mem:: transmute :: <
807
+ * mut libc:: c_void ,
808
+ unsafe extern "C" fn ( libc:: c_int ) -> libc:: c_int ,
809
+ > ( ptr) ;
810
+ match epoll_create1 ( CLOEXEC ) {
811
+ -1 => return Err ( io:: Error :: last_os_error ( ) ) ,
812
+ fd => fd,
813
+ }
814
+ }
815
+ } ;
816
+
785
817
let event_fd = syscall ! ( eventfd( 0 , libc:: EFD_CLOEXEC | libc:: EFD_NONBLOCK ) ) ?;
786
818
let reactor = Reactor { epoll_fd, event_fd } ;
787
819
reactor. register ( event_fd, !0 ) ?;
@@ -791,8 +823,12 @@ mod sys {
791
823
pub fn register ( & self , fd : RawFd , key : usize ) -> io:: Result < ( ) > {
792
824
let flags = syscall ! ( fcntl( fd, libc:: F_GETFL ) ) ?;
793
825
syscall ! ( fcntl( fd, libc:: F_SETFL , flags | libc:: O_NONBLOCK ) ) ?;
794
- let ev = & mut EpollEvent :: new ( 0 , key as u64 ) ;
795
- epoll_ctl ( self . epoll_fd , EpollOp :: EpollCtlAdd , fd, Some ( ev) )
826
+ let mut ev = libc:: epoll_event {
827
+ events : 0 ,
828
+ u64 : key as u64 ,
829
+ } ;
830
+ syscall ! ( epoll_ctl( self . epoll_fd, libc:: EPOLL_CTL_ADD , fd, & mut ev) ) ?;
831
+ Ok ( ( ) )
796
832
}
797
833
pub fn reregister ( & self , fd : RawFd , key : usize , read : bool , write : bool ) -> io:: Result < ( ) > {
798
834
let mut flags = libc:: EPOLLONESHOT ;
@@ -802,11 +838,21 @@ mod sys {
802
838
if write {
803
839
flags |= write_flags ( ) ;
804
840
}
805
- let ev = & mut EpollEvent :: new ( flags, key as u64 ) ;
806
- epoll_ctl ( self . epoll_fd , EpollOp :: EpollCtlMod , fd, Some ( ev) )
841
+ let mut ev = libc:: epoll_event {
842
+ events : flags as _ ,
843
+ u64 : key as u64 ,
844
+ } ;
845
+ syscall ! ( epoll_ctl( self . epoll_fd, libc:: EPOLL_CTL_MOD , fd, & mut ev) ) ?;
846
+ Ok ( ( ) )
807
847
}
808
848
pub fn deregister ( & self , fd : RawFd ) -> io:: Result < ( ) > {
809
- epoll_ctl ( self . epoll_fd , EpollOp :: EpollCtlDel , fd, None )
849
+ syscall ! ( epoll_ctl(
850
+ self . epoll_fd,
851
+ libc:: EPOLL_CTL_DEL ,
852
+ fd,
853
+ ptr:: null_mut( )
854
+ ) ) ?;
855
+ Ok ( ( ) )
810
856
}
811
857
pub fn wait ( & self , events : & mut Events , timeout : Option < Duration > ) -> io:: Result < usize > {
812
858
let timeout_ms = timeout
@@ -819,7 +865,14 @@ mod sys {
819
865
} )
820
866
. and_then ( |t| t. as_millis ( ) . try_into ( ) . ok ( ) )
821
867
. unwrap_or ( -1 ) ;
822
- events. len = epoll_wait ( self . epoll_fd , & mut events. list , timeout_ms) ?;
868
+
869
+ let res = syscall ! ( epoll_wait(
870
+ self . epoll_fd,
871
+ events. list. as_mut_ptr( ) as * mut libc:: epoll_event,
872
+ events. list. len( ) as libc:: c_int,
873
+ timeout_ms as libc:: c_int,
874
+ ) ) ?;
875
+ events. len = res as usize ;
823
876
824
877
let mut buf = [ 0u8 ; 8 ] ;
825
878
let _ = syscall ! ( read(
@@ -841,28 +894,29 @@ mod sys {
841
894
Ok ( ( ) )
842
895
}
843
896
}
844
- fn read_flags ( ) -> EpollFlags {
897
+ fn read_flags ( ) -> libc :: c_int {
845
898
libc:: EPOLLIN | libc:: EPOLLRDHUP | libc:: EPOLLHUP | libc:: EPOLLERR | libc:: EPOLLPRI
846
899
}
847
- fn write_flags ( ) -> EpollFlags {
900
+ fn write_flags ( ) -> libc :: c_int {
848
901
libc:: EPOLLOUT | libc:: EPOLLHUP | libc:: EPOLLERR
849
902
}
850
903
851
904
pub struct Events {
852
- list : Box < [ EpollEvent ] > ,
905
+ list : Box < [ libc :: epoll_event ] > ,
853
906
len : usize ,
854
907
}
855
908
impl Events {
856
909
pub fn new ( ) -> Events {
857
- let list = vec ! [ EpollEvent :: empty( ) ; 1000 ] . into_boxed_slice ( ) ;
910
+ let ev = libc:: epoll_event { events : 0 , u64 : 0 } ;
911
+ let list = vec ! [ ev; 1000 ] . into_boxed_slice ( ) ;
858
912
let len = 0 ;
859
913
Events { list, len }
860
914
}
861
915
pub fn iter ( & self ) -> impl Iterator < Item = Event > + ' _ {
862
916
self . list [ ..self . len ] . iter ( ) . map ( |ev| Event {
863
- readable : ( ev. events ( ) & read_flags ( ) ) != 0 ,
864
- writable : ( ev. events ( ) & write_flags ( ) ) != 0 ,
865
- key : ev. data ( ) as usize ,
917
+ readable : ( ev. events as libc :: c_int & read_flags ( ) ) != 0 ,
918
+ writable : ( ev. events as libc :: c_int & write_flags ( ) ) != 0 ,
919
+ key : ev. u64 as usize ,
866
920
} )
867
921
}
868
922
}
0 commit comments