@@ -67,25 +67,70 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
67
67
args:: init ( argc, argv) ;
68
68
69
69
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 ( ) ;
89
134
}
90
135
}
91
136
}
0 commit comments