@@ -18,7 +18,7 @@ use path::Path;
18
18
use sys:: fd:: FileDesc ;
19
19
use sys:: fs:: { File , OpenOptions } ;
20
20
use sys:: pipe:: { self , AnonPipe } ;
21
- use sys:: { self , cvt} ;
21
+ use sys:: cvt;
22
22
23
23
////////////////////////////////////////////////////////////////////////////////
24
24
// Command
@@ -145,78 +145,32 @@ impl Command {
145
145
146
146
pub fn spawn ( & mut self , default : Stdio , needs_stdin : bool )
147
147
-> io:: Result < ( Process , StdioPipes ) > {
148
- const CLOEXEC_MSG_FOOTER : & ' static [ u8 ] = b"NOEX" ;
149
-
150
148
if self . saw_nul {
151
149
return Err ( io:: Error :: new ( ErrorKind :: InvalidInput ,
152
150
"nul byte found in provided data" ) ) ;
153
151
}
154
152
155
153
let ( ours, theirs) = self . setup_io ( default, needs_stdin) ?;
156
- let ( input, output) = sys:: pipe:: anon_pipe ( ) ?;
157
154
158
155
let pid = unsafe {
159
- match cvt ( libc:: clone ( 0 ) ) ? {
156
+ match cvt ( libc:: clone ( libc :: CLONE_VFORK ) ) ? {
160
157
0 => {
161
- drop ( input) ;
162
158
let err = self . do_exec ( theirs) ;
163
- let errno = err. raw_os_error ( ) . unwrap_or ( libc:: EINVAL ) as u32 ;
164
- let bytes = [
165
- ( errno >> 24 ) as u8 ,
166
- ( errno >> 16 ) as u8 ,
167
- ( errno >> 8 ) as u8 ,
168
- ( errno >> 0 ) as u8 ,
169
- CLOEXEC_MSG_FOOTER [ 0 ] , CLOEXEC_MSG_FOOTER [ 1 ] ,
170
- CLOEXEC_MSG_FOOTER [ 2 ] , CLOEXEC_MSG_FOOTER [ 3 ]
171
- ] ;
172
- // pipe I/O up to PIPE_BUF bytes should be atomic, and then
173
- // we want to be sure we *don't* run at_exit destructors as
174
- // we're being torn down regardless
175
- assert ! ( output. write( & bytes) . is_ok( ) ) ;
176
- let _ = libc:: exit ( 1 ) ;
159
+ let _ = libc:: exit ( ( -err. raw_os_error ( ) . unwrap_or ( libc:: EINVAL ) ) as usize ) ;
177
160
unreachable ! ( ) ;
178
161
}
179
162
n => n as pid_t ,
180
163
}
181
164
} ;
182
165
183
- let mut p = Process { pid : pid, status : None } ;
184
- drop ( output) ;
185
- let mut bytes = [ 0 ; 8 ] ;
186
-
187
- // loop to handle EINTR
188
- loop {
189
- match input. read ( & mut bytes) {
190
- Ok ( 0 ) => return Ok ( ( p, ours) ) ,
191
- Ok ( 8 ) => {
192
- assert ! ( combine( CLOEXEC_MSG_FOOTER ) == combine( & bytes[ 4 .. 8 ] ) ,
193
- "Validation on the CLOEXEC pipe failed: {:?}" , bytes) ;
194
- let errno = combine ( & bytes[ 0 .. 4 ] ) ;
195
- assert ! ( p. wait( ) . is_ok( ) ,
196
- "wait() should either return Ok or panic" ) ;
197
- return Err ( Error :: from_raw_os_error ( errno) )
198
- }
199
- Err ( ref e) if e. kind ( ) == ErrorKind :: Interrupted => { }
200
- Err ( e) => {
201
- assert ! ( p. wait( ) . is_ok( ) ,
202
- "wait() should either return Ok or panic" ) ;
203
- panic ! ( "the CLOEXEC pipe failed: {:?}" , e)
204
- } ,
205
- Ok ( ..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
206
- assert ! ( p. wait( ) . is_ok( ) ,
207
- "wait() should either return Ok or panic" ) ;
208
- panic ! ( "short read on the CLOEXEC pipe" )
209
- }
166
+ let mut status_mux = 0 ;
167
+ if cvt ( libc:: waitpid ( pid, & mut status_mux, libc:: WNOHANG ) ) ? == pid {
168
+ match libc:: Error :: demux ( status_mux) {
169
+ Ok ( status) => Ok ( ( Process { pid : pid, status : Some ( ExitStatus :: from ( status as c_int ) ) } , ours) ) ,
170
+ Err ( err) => Err ( io:: Error :: from_raw_os_error ( err. errno ) ) ,
210
171
}
211
- }
212
-
213
- fn combine ( arr : & [ u8 ] ) -> i32 {
214
- let a = arr[ 0 ] as u32 ;
215
- let b = arr[ 1 ] as u32 ;
216
- let c = arr[ 2 ] as u32 ;
217
- let d = arr[ 3 ] as u32 ;
218
-
219
- ( ( a << 24 ) | ( b << 16 ) | ( c << 8 ) | ( d << 0 ) ) as i32
172
+ } else {
173
+ Ok ( ( Process { pid : pid, status : None } , ours) )
220
174
}
221
175
}
222
176
0 commit comments