@@ -77,35 +77,65 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
77
77
}
78
78
79
79
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;
102
107
}
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.
103
120
libc:: abort ( ) ;
104
121
}
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 {
109
139
if libc:: open ( "/dev/null\0 " . as_ptr ( ) . cast ( ) , libc:: O_RDWR , 0 ) == -1 {
110
140
// If the stream is closed but we failed to reopen it, abort the
111
141
// process. Otherwise we wouldn't preserve the safety of
@@ -114,15 +144,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
114
144
libc:: abort ( ) ;
115
145
}
116
146
}
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
- }
126
147
}
127
148
}
128
149
}
0 commit comments