@@ -77,35 +77,65 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
7777 }
7878
7979 unsafe fn sanitize_standard_fds ( ) {
80- #[ cfg( not( miri) ) ]
81- // The standard fds are always available in Miri.
82- cfg_if:: cfg_if! {
83- if #[ cfg( not( any(
84- target_os = "emscripten" ,
85- target_os = "fuchsia" ,
86- target_os = "vxworks" ,
87- // The poll on Darwin doesn't set POLLNVAL for closed fds.
88- target_os = "macos" ,
89- target_os = "ios" ,
90- target_os = "redox" ,
91- target_os = "l4re" ,
92- ) ) ) ] {
93- use crate :: sys:: os:: errno;
94- let pfds: & mut [ _] = & mut [
95- libc:: pollfd { fd: 0 , events: 0 , revents: 0 } ,
96- libc:: pollfd { fd: 1 , events: 0 , revents: 0 } ,
97- libc:: pollfd { fd: 2 , events: 0 , revents: 0 } ,
98- ] ;
99- while libc:: poll( pfds. as_mut_ptr( ) , 3 , 0 ) == -1 {
100- if errno( ) == libc:: EINTR {
101- continue ;
80+ // fast path with a single syscall for systems with poll()
81+ #[ cfg( not( any(
82+ miri,
83+ target_os = "emscripten" ,
84+ target_os = "fuchsia" ,
85+ target_os = "vxworks" ,
86+ // The poll on Darwin doesn't set POLLNVAL for closed fds.
87+ target_os = "macos" ,
88+ target_os = "ios" ,
89+ target_os = "redox" ,
90+ target_os = "l4re" ,
91+ ) ) ) ]
92+ ' poll: {
93+ use crate :: sys:: os:: errno;
94+ let pfds: & mut [ _ ] = & mut [
95+ libc:: pollfd { fd : 0 , events : 0 , revents : 0 } ,
96+ libc:: pollfd { fd : 1 , events : 0 , revents : 0 } ,
97+ libc:: pollfd { fd : 2 , events : 0 , revents : 0 } ,
98+ ] ;
99+
100+ while libc:: poll ( pfds. as_mut_ptr ( ) , 3 , 0 ) == -1 {
101+ match errno ( ) {
102+ libc:: EINTR => continue ,
103+ libc:: EINVAL | libc:: EAGAIN | libc:: ENOMEM => {
104+ // RLIMIT_NOFILE or temporary allocation failures
105+ // may be preventing use of poll(), fall back to fcntl
106+ break ' poll;
102107 }
108+ _ => libc:: abort ( ) ,
109+ }
110+ }
111+ for pfd in pfds {
112+ if pfd. revents & libc:: POLLNVAL == 0 {
113+ continue ;
114+ }
115+ if libc:: open ( "/dev/null\0 " . as_ptr ( ) . cast ( ) , libc:: O_RDWR , 0 ) == -1 {
116+ // If the stream is closed but we failed to reopen it, abort the
117+ // process. Otherwise we wouldn't preserve the safety of
118+ // operations on the corresponding Rust object Stdin, Stdout, or
119+ // Stderr.
103120 libc:: abort ( ) ;
104121 }
105- for pfd in pfds {
106- if pfd. revents & libc:: POLLNVAL == 0 {
107- continue ;
108- }
122+ }
123+ return ;
124+ }
125+
126+ // fallback in case poll isn't available or limited by RLIMIT_NOFILE
127+ #[ cfg( not( any(
128+ // The standard fds are always available in Miri.
129+ miri,
130+ target_os = "emscripten" ,
131+ target_os = "fuchsia" ,
132+ target_os = "vxworks" ,
133+ target_os = "l4re" ,
134+ ) ) ) ]
135+ {
136+ use crate :: sys:: os:: errno;
137+ for fd in 0 ..3 {
138+ if libc:: fcntl ( fd, libc:: F_GETFD ) == -1 && errno ( ) == libc:: EBADF {
109139 if libc:: open ( "/dev/null\0 " . as_ptr ( ) . cast ( ) , libc:: O_RDWR , 0 ) == -1 {
110140 // If the stream is closed but we failed to reopen it, abort the
111141 // process. Otherwise we wouldn't preserve the safety of
@@ -114,15 +144,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
114144 libc:: abort ( ) ;
115145 }
116146 }
117- } else if #[ cfg( any( target_os = "macos" , target_os = "ios" , target_os = "redox" ) ) ] {
118- use crate :: sys:: os:: errno;
119- for fd in 0 ..3 {
120- if libc:: fcntl( fd, libc:: F_GETFD ) == -1 && errno( ) == libc:: EBADF {
121- if libc:: open( "/dev/null\0 " . as_ptr( ) . cast( ) , libc:: O_RDWR , 0 ) == -1 {
122- libc:: abort( ) ;
123- }
124- }
125- }
126147 }
127148 }
128149 }
0 commit comments