@@ -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
}
@@ -886,10 +940,9 @@ mod sys {
886
940
use std:: io:: { self , Read , Write } ;
887
941
use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
888
942
use std:: os:: unix:: net:: UnixStream ;
943
+ use std:: ptr;
889
944
use std:: time:: Duration ;
890
945
891
- use crate :: sys:: event:: { kevent_ts, kqueue, KEvent } ;
892
-
893
946
macro_rules! syscall {
894
947
( $fn: ident $args: tt) => { {
895
948
let res = unsafe { libc:: $fn $args } ;
@@ -908,7 +961,7 @@ mod sys {
908
961
}
909
962
impl Reactor {
910
963
pub fn new ( ) -> io:: Result < Reactor > {
911
- let kqueue_fd = kqueue ( ) ?;
964
+ let kqueue_fd = syscall ! ( kqueue( ) ) ?;
912
965
syscall ! ( fcntl( kqueue_fd, libc:: F_SETFD , libc:: FD_CLOEXEC ) ) ?;
913
966
let ( read_stream, write_stream) = UnixStream :: pair ( ) ?;
914
967
read_stream. set_nonblocking ( true ) ?;
@@ -939,38 +992,78 @@ mod sys {
939
992
} else {
940
993
write_flags |= libc:: EV_DELETE ;
941
994
}
942
- let udata = key as _ ;
943
995
let changelist = [
944
- KEvent :: new ( fd as _ , libc:: EVFILT_READ , read_flags, 0 , 0 , udata) ,
945
- KEvent :: new ( fd as _ , libc:: EVFILT_WRITE , write_flags, 0 , 0 , udata) ,
996
+ libc:: kevent {
997
+ ident : fd as _ ,
998
+ filter : libc:: EVFILT_READ ,
999
+ flags : read_flags,
1000
+ fflags : 0 ,
1001
+ data : 0 ,
1002
+ udata : key as _ ,
1003
+ } ,
1004
+ libc:: kevent {
1005
+ ident : fd as _ ,
1006
+ filter : libc:: EVFILT_WRITE ,
1007
+ flags : write_flags,
1008
+ fflags : 0 ,
1009
+ data : 0 ,
1010
+ udata : key as _ ,
1011
+ } ,
946
1012
] ;
947
1013
let mut eventlist = changelist;
948
- kevent_ts ( self . kqueue_fd , & changelist, & mut eventlist, None ) ?;
1014
+ syscall ! ( kevent(
1015
+ self . kqueue_fd,
1016
+ changelist. as_ptr( ) as * const libc:: kevent,
1017
+ changelist. len( ) as _,
1018
+ eventlist. as_mut_ptr( ) as * mut libc:: kevent,
1019
+ eventlist. len( ) as _,
1020
+ ptr:: null( ) ,
1021
+ ) ) ?;
949
1022
for ev in & eventlist {
950
1023
// Explanation for ignoring EPIPE: https://github.com/tokio-rs/mio/issues/582
951
- let ( flags, data) = ( ev. flags ( ) , ev. data ( ) ) ;
952
- if ( flags & libc:: EV_ERROR ) == 1
953
- && data != 0
954
- && data != libc:: ENOENT as _
955
- && data != libc:: EPIPE as _
1024
+ if ( ev. flags & libc:: EV_ERROR ) != 0
1025
+ && ev. data != 0
1026
+ && ev. data != libc:: ENOENT as _
1027
+ && ev. data != libc:: EPIPE as _
956
1028
{
957
- return Err ( io:: Error :: from_raw_os_error ( data as _ ) ) ;
1029
+ return Err ( io:: Error :: from_raw_os_error ( ev . data as _ ) ) ;
958
1030
}
959
1031
}
960
1032
Ok ( ( ) )
961
1033
}
962
1034
pub fn deregister ( & self , fd : RawFd ) -> io:: Result < ( ) > {
963
1035
let flags = libc:: EV_DELETE | libc:: EV_RECEIPT ;
964
1036
let changelist = [
965
- KEvent :: new ( fd as _ , libc:: EVFILT_WRITE , flags, 0 , 0 , 0 ) ,
966
- KEvent :: new ( fd as _ , libc:: EVFILT_READ , flags, 0 , 0 , 0 ) ,
1037
+ libc:: kevent {
1038
+ ident : fd as _ ,
1039
+ filter : libc:: EVFILT_READ ,
1040
+ flags : flags,
1041
+ fflags : 0 ,
1042
+ data : 0 ,
1043
+ udata : 0 as _ ,
1044
+ } ,
1045
+ libc:: kevent {
1046
+ ident : fd as _ ,
1047
+ filter : libc:: EVFILT_WRITE ,
1048
+ flags : flags,
1049
+ fflags : 0 ,
1050
+ data : 0 ,
1051
+ udata : 0 as _ ,
1052
+ } ,
967
1053
] ;
968
1054
let mut eventlist = changelist;
969
- kevent_ts ( self . kqueue_fd , & changelist, & mut eventlist, None ) ?;
1055
+ syscall ! ( kevent(
1056
+ self . kqueue_fd,
1057
+ changelist. as_ptr( ) as * const libc:: kevent,
1058
+ changelist. len( ) as _,
1059
+ eventlist. as_mut_ptr( ) as * mut libc:: kevent,
1060
+ eventlist. len( ) as _,
1061
+ ptr:: null( ) ,
1062
+ ) ) ?;
970
1063
for ev in & eventlist {
971
- let ( flags, data ) = ( ev. flags ( ) , ev. data ( ) ) ;
972
- if ( flags & libc :: EV_ERROR == 1 ) && data != 0 && data != libc :: ENOENT as _ {
973
- return Err ( io:: Error :: from_raw_os_error ( data as _ ) ) ;
1064
+ if ( ev . flags & libc :: EV_ERROR ) != 0 && ev. data != 0 && ev. data != libc :: ENOENT as _
1065
+ {
1066
+ return Err ( io:: Error :: from_raw_os_error ( ev . data as _ ) ) ;
974
1067
}
975
1068
}
976
1069
Ok ( ( ) )
@@ -980,7 +1073,20 @@ mod sys {
980
1073
tv_sec : t. as_secs ( ) as libc:: time_t ,
981
1074
tv_nsec : t. subsec_nanos ( ) as libc:: c_long ,
982
1075
} ) ;
983
- events. len = kevent_ts ( self . kqueue_fd , & [ ] , & mut events. list , timeout) ?;
1076
+ let changelist = [ ] ;
1077
+ let eventlist = & mut events. list ;
1078
+ let res = syscall ! ( kevent(
1079
+ self . kqueue_fd,
1080
+ changelist. as_ptr( ) as * const libc:: kevent,
1081
+ changelist. len( ) as _,
1082
+ eventlist. as_mut_ptr( ) as * mut libc:: kevent,
1083
+ eventlist. len( ) as _,
1084
+ match & timeout {
1085
+ None => ptr:: null( ) ,
1086
+ Some ( t) => t,
1087
+ }
1088
+ ) ) ?;
1089
+ events. len = res as usize ;
984
1090
985
1091
while ( & self . read_stream ) . read ( & mut [ 0 ; 64 ] ) . is_ok ( ) { }
986
1092
self . reregister ( self . read_stream . as_raw_fd ( ) , !0 , true , false ) ?;
@@ -994,13 +1100,19 @@ mod sys {
994
1100
}
995
1101
996
1102
pub struct Events {
997
- list : Box < [ KEvent ] > ,
1103
+ list : Box < [ libc :: kevent ] > ,
998
1104
len : usize ,
999
1105
}
1000
1106
impl Events {
1001
1107
pub fn new ( ) -> Events {
1002
- let flags = 0 ;
1003
- let event = KEvent :: new ( 0 , 0 , flags, 0 , 0 , 0 ) ;
1108
+ let event = libc:: kevent {
1109
+ ident : 0 as _ ,
1110
+ filter : 0 ,
1111
+ flags : 0 ,
1112
+ fflags : 0 ,
1113
+ data : 0 ,
1114
+ udata : 0 as _ ,
1115
+ } ;
1004
1116
let list = vec ! [ event; 1000 ] . into_boxed_slice ( ) ;
1005
1117
let len = 0 ;
1006
1118
Events { list, len }
@@ -1011,13 +1123,14 @@ mod sys {
1011
1123
//
1012
1124
// https://github.com/golang/go/commit/23aad448b1e3f7c3b4ba2af90120bde91ac865b4
1013
1125
self . list [ ..self . len ] . iter ( ) . map ( |ev| Event {
1014
- readable : ev. filter ( ) == libc:: EVFILT_READ ,
1015
- writable : ev. filter ( ) == libc:: EVFILT_WRITE
1016
- || ( ev. filter ( ) == libc:: EVFILT_READ && ( ev. flags ( ) & libc:: EV_EOF ) != 0 ) ,
1017
- key : ev. udata ( ) as usize ,
1126
+ readable : ev. filter == libc:: EVFILT_READ ,
1127
+ writable : ev. filter == libc:: EVFILT_WRITE
1128
+ || ( ev. filter == libc:: EVFILT_READ && ( ev. flags & libc:: EV_EOF ) != 0 ) ,
1129
+ key : ev. udata as usize ,
1018
1130
} )
1019
1131
}
1020
1132
}
1133
+ unsafe impl Send for Events { }
1021
1134
pub struct Event {
1022
1135
pub readable : bool ,
1023
1136
pub writable : bool ,
@@ -1031,6 +1144,7 @@ mod sys {
1031
1144
use std:: convert:: TryInto ;
1032
1145
use std:: io;
1033
1146
use std:: os:: windows:: io:: { AsRawSocket , RawSocket } ;
1147
+ use std:: ptr;
1034
1148
use std:: time:: Duration ;
1035
1149
1036
1150
use wepoll_sys_stjepang as we;
@@ -1115,7 +1229,7 @@ mod sys {
1115
1229
self . handle,
1116
1230
we:: EPOLL_CTL_DEL as libc:: c_int,
1117
1231
sock as we:: SOCKET ,
1118
- 0 as * mut we :: epoll_event ,
1232
+ ptr :: null_mut ( ) ,
1119
1233
) ) ?;
1120
1234
Ok ( ( ) )
1121
1235
}
@@ -1148,7 +1262,7 @@ mod sys {
1148
1262
self . handle as winapi:: um:: winnt:: HANDLE ,
1149
1263
0 ,
1150
1264
0 ,
1151
- 0 as * mut _ ,
1265
+ ptr :: null_mut ( ) ,
1152
1266
) ;
1153
1267
}
1154
1268
Ok ( ( ) )
0 commit comments