diff --git a/src/common/file_descriptor.rs b/src/common/file_descriptor.rs new file mode 100644 index 000000000..33019a6bf --- /dev/null +++ b/src/common/file_descriptor.rs @@ -0,0 +1,26 @@ +use std::ffi::CString; +use std::io; +use std::io::Error; +use std::io::ErrorKind; +use std::io::Read; + +pub struct FileDescriptor(libc::c_int); + +impl FileDescriptor { + pub fn new(file_descriptor_number: libc::c_int) -> FileDescriptor { + FileDescriptor(file_descriptor_number) + } +} + +impl Read for FileDescriptor { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let file_descriptor: libc::c_int = self.0; + let count = + unsafe { libc::read(file_descriptor, buf.as_mut_ptr() as *mut libc::c_void, 1) }; + if count < 0 { + Err(Error::new(ErrorKind::Other, "read error")) + } else { + Ok(count as usize) + } + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index 8694cd5f7..63a6bd39f 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,5 +1,6 @@ pub mod mmap; pub mod slice; +mod file_descriptor; #[cfg(test)] pub mod stdio; diff --git a/src/common/stdio.rs b/src/common/stdio.rs index 26d72c431..8e26c67ce 100644 --- a/src/common/stdio.rs +++ b/src/common/stdio.rs @@ -1,7 +1,7 @@ +use crate::common::file_descriptor::FileDescriptor; use libc; -use std::fs::File; +use std::io::BufReader; use std::io::Read; -use std::os::unix::io::FromRawFd; // A struct to hold the references to the base stdout and the captured one pub struct StdioCapturer { @@ -17,7 +17,15 @@ pub struct StdioCapturer { impl StdioCapturer { fn pipe() -> (libc::c_int, libc::c_int) { let mut fds = [0; 2]; + + #[cfg(not(target_os = "windows"))] assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0); + #[cfg(target_os = "windows")] + assert_eq!( + unsafe { libc::pipe(fds.as_mut_ptr(), 1000, libc::O_TEXT) }, + 0 + ); + (fds[0], fds[1]) } @@ -28,9 +36,6 @@ impl StdioCapturer { let (stdout_reader, stdout_writer) = Self::pipe(); let (stderr_reader, stderr_writer) = Self::pipe(); - // std::io::stdout().flush().unwrap(); - // std::io::stderr().flush().unwrap(); - assert!(unsafe { libc::dup2(stdout_writer, libc::STDOUT_FILENO) } > -1); assert!(unsafe { libc::dup2(stderr_writer, libc::STDERR_FILENO) } > -1); @@ -48,28 +53,23 @@ impl StdioCapturer { } } - pub fn end(self) -> (String, String) { + pub fn end(self) -> Result<(String, String), std::io::Error> { // The Stdio passed into the Command took over (and closed) std{out, err} // so we should restore them as they were. assert!(unsafe { libc::dup2(self.stdout_backup, libc::STDOUT_FILENO) } > -1); assert!(unsafe { libc::dup2(self.stderr_backup, libc::STDERR_FILENO) } > -1); - // assert_eq!(unsafe { libc::close(self.stdout_backup) }, 0); - // assert_eq!(unsafe { libc::close(self.stderr_backup) }, 0); + let fd = FileDescriptor::new(self.stdout_reader); + let mut reader = BufReader::new(fd); + let mut stdout_read = "".to_string(); + let _ = reader.read_to_string(&mut stdout_read)?; - let mut stdout_read = String::new(); - let mut stdout_file: File = unsafe { FromRawFd::from_raw_fd(self.stdout_reader) }; - stdout_file - .read_to_string(&mut stdout_read) - .expect("failed to read from stdout file"); + let fd = FileDescriptor::new(self.stderr_reader); + let mut reader = BufReader::new(fd); + let mut stderr_read = "".to_string(); + let _ = reader.read_to_string(&mut stderr_read)?; - let mut stderr_read = String::new(); - let mut stderr_file: File = unsafe { FromRawFd::from_raw_fd(self.stderr_reader) }; - stderr_file - .read_to_string(&mut stderr_read) - .expect("failed to read from stdout file"); - - (stdout_read, stderr_read) + Ok((stdout_read, stderr_read)) } } diff --git a/src/emtests/_common.rs b/src/emtests/_common.rs index 75604d2d2..78b169f54 100644 --- a/src/emtests/_common.rs +++ b/src/emtests/_common.rs @@ -26,7 +26,7 @@ macro_rules! assert_emscripten_output { $args, ) .unwrap(); - let output = capturer.end().0; + let output = capturer.end().unwrap().0; let expected_output = include_str!($expected); assert_eq!(output, expected_output); }};