@@ -67,25 +67,70 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
6767 args:: init ( argc, argv) ;
6868
6969 unsafe fn sanitize_standard_fds ( ) {
70- cfg_if:: cfg_if! {
71- if #[ cfg( not( any(
72- // The standard fds are always available in Miri.
73- miri,
74- target_os = "emscripten" ,
75- target_os = "fuchsia" ,
76- target_os = "vxworks" ,
77- target_os = "l4re" ,
78- ) ) ) ] {
79- use crate :: sys:: os:: errno;
80- for fd in 0 ..3 {
81- if libc:: fcntl( fd, libc:: F_GETFD ) == -1 && errno( ) == libc:: EBADF {
82- if libc:: open( "/dev/null\0 " . as_ptr( ) . cast( ) , libc:: O_RDWR , 0 ) == -1 {
83- // If the stream is closed but we failed to reopen it, abort the
84- // process. Otherwise we wouldn't preserve the safety of
85- // operations on the corresponding Rust object Stdin, Stdout, or
86- // Stderr.
87- libc:: abort( ) ;
88- }
70+ // fast path with a single syscall for systems with poll()
71+ #[ cfg( not( any(
72+ miri,
73+ target_os = "emscripten" ,
74+ target_os = "fuchsia" ,
75+ target_os = "vxworks" ,
76+ // The poll on Darwin doesn't set POLLNVAL for closed fds.
77+ target_os = "macos" ,
78+ target_os = "ios" ,
79+ target_os = "redox" ,
80+ target_os = "l4re" ,
81+ ) ) ) ]
82+ ' poll: {
83+ use crate :: sys:: os:: errno;
84+ let pfds: & mut [ _ ] = & mut [
85+ libc:: pollfd { fd : 0 , events : 0 , revents : 0 } ,
86+ libc:: pollfd { fd : 1 , events : 0 , revents : 0 } ,
87+ libc:: pollfd { fd : 2 , events : 0 , revents : 0 } ,
88+ ] ;
89+
90+ while libc:: poll ( pfds. as_mut_ptr ( ) , 3 , 0 ) == -1 {
91+ if errno ( ) == libc:: EINTR {
92+ continue ;
93+ }
94+ if errno ( ) == libc:: EINVAL {
95+ // RLIMIT_NOFILE may be preventing use of poll()
96+ break ' poll;
97+ }
98+ libc:: abort ( ) ;
99+ }
100+ for pfd in pfds {
101+ if pfd. revents & libc:: POLLNVAL == 0 {
102+ continue ;
103+ }
104+ if libc:: open ( "/dev/null\0 " . as_ptr ( ) . cast ( ) , libc:: O_RDWR , 0 ) == -1 {
105+ // If the stream is closed but we failed to reopen it, abort the
106+ // process. Otherwise we wouldn't preserve the safety of
107+ // operations on the corresponding Rust object Stdin, Stdout, or
108+ // Stderr.
109+ libc:: abort ( ) ;
110+ }
111+ }
112+ return ;
113+ }
114+
115+ // fallback in case poll isn't available or limited by RLIMIT_NOFILE
116+ #[ cfg( not( any(
117+ // The standard fds are always available in Miri.
118+ miri,
119+ target_os = "emscripten" ,
120+ target_os = "fuchsia" ,
121+ target_os = "vxworks" ,
122+ target_os = "l4re" ,
123+ ) ) ) ]
124+ {
125+ use crate :: sys:: os:: errno;
126+ for fd in 0 ..3 {
127+ if libc:: fcntl ( fd, libc:: F_GETFD ) == -1 && errno ( ) == libc:: EBADF {
128+ if libc:: open ( "/dev/null\0 " . as_ptr ( ) . cast ( ) , libc:: O_RDWR , 0 ) == -1 {
129+ // If the stream is closed but we failed to reopen it, abort the
130+ // process. Otherwise we wouldn't preserve the safety of
131+ // operations on the corresponding Rust object Stdin, Stdout, or
132+ // Stderr.
133+ libc:: abort ( ) ;
89134 }
90135 }
91136 }
0 commit comments