diff options
| author | Jeremy Soller <jackpot51@gmail.com> | 2016-11-09 20:52:30 -0700 |
|---|---|---|
| committer | Jeremy Soller <jackpot51@gmail.com> | 2016-11-09 20:52:30 -0700 |
| commit | ced32a08f3bf7325bf3fe6488e21b108f996abc5 (patch) | |
| tree | d9af3131bf73f5f94a62727eccfcb66fbf627376 /src/libstd/sys | |
| parent | 01e837807095e99d68ecf9c0b38527288281dd02 (diff) | |
| download | rust-ced32a08f3bf7325bf3fe6488e21b108f996abc5.tar.gz rust-ced32a08f3bf7325bf3fe6488e21b108f996abc5.zip | |
Fix exec
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/redox/process.rs | 66 |
1 files changed, 10 insertions, 56 deletions
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index b6968f285d7..ad50d1de283 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -18,7 +18,7 @@ use path::Path; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; use sys::pipe::{self, AnonPipe}; -use sys::{self, cvt}; +use sys::cvt; //////////////////////////////////////////////////////////////////////////////// // Command @@ -145,78 +145,32 @@ impl Command { pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) -> io::Result<(Process, StdioPipes)> { - const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; - if self.saw_nul { return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")); } let (ours, theirs) = self.setup_io(default, needs_stdin)?; - let (input, output) = sys::pipe::anon_pipe()?; let pid = unsafe { - match cvt(libc::clone(0))? { + match cvt(libc::clone(libc::CLONE_VFORK))? { 0 => { - drop(input); let err = self.do_exec(theirs); - let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; - let bytes = [ - (errno >> 24) as u8, - (errno >> 16) as u8, - (errno >> 8) as u8, - (errno >> 0) as u8, - CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1], - CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3] - ]; - // pipe I/O up to PIPE_BUF bytes should be atomic, and then - // we want to be sure we *don't* run at_exit destructors as - // we're being torn down regardless - assert!(output.write(&bytes).is_ok()); - let _ = libc::exit(1); + let _ = libc::exit((-err.raw_os_error().unwrap_or(libc::EINVAL)) as usize); unreachable!(); } n => n as pid_t, } }; - let mut p = Process { pid: pid, status: None }; - drop(output); - let mut bytes = [0; 8]; - - // loop to handle EINTR - loop { - match input.read(&mut bytes) { - Ok(0) => return Ok((p, ours)), - Ok(8) => { - assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]), - "Validation on the CLOEXEC pipe failed: {:?}", bytes); - let errno = combine(&bytes[0.. 4]); - assert!(p.wait().is_ok(), - "wait() should either return Ok or panic"); - return Err(Error::from_raw_os_error(errno)) - } - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - Err(e) => { - assert!(p.wait().is_ok(), - "wait() should either return Ok or panic"); - panic!("the CLOEXEC pipe failed: {:?}", e) - }, - Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic - assert!(p.wait().is_ok(), - "wait() should either return Ok or panic"); - panic!("short read on the CLOEXEC pipe") - } + let mut status_mux = 0; + if cvt(libc::waitpid(pid, &mut status_mux, libc::WNOHANG))? == pid { + match libc::Error::demux(status_mux) { + Ok(status) => Ok((Process { pid: pid, status: Some(ExitStatus::from(status as c_int)) }, ours)), + Err(err) => Err(io::Error::from_raw_os_error(err.errno)), } - } - - fn combine(arr: &[u8]) -> i32 { - let a = arr[0] as u32; - let b = arr[1] as u32; - let c = arr[2] as u32; - let d = arr[3] as u32; - - ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32 + } else { + Ok((Process { pid: pid, status: None }, ours)) } } |
