diff --git a/src/libstd/rt/io/pipe.rs b/src/libstd/rt/io/pipe.rs index 979a1dfc65e3..ec9a4a0101fe 100644 --- a/src/libstd/rt/io/pipe.rs +++ b/src/libstd/rt/io/pipe.rs @@ -16,13 +16,45 @@ use prelude::*; use super::{Reader, Writer}; use rt::io::{io_error, EndOfFile}; -use rt::rtio::RtioPipe; +use rt::io::native::file; +use rt::rtio::{RtioPipe, with_local_io}; pub struct PipeStream { priv obj: ~RtioPipe, } impl PipeStream { + /// Consumes a file descriptor to return a pipe stream that will have + /// synchronous, but non-blocking reads/writes. This is useful if the file + /// descriptor is acquired via means other than the standard methods. + /// + /// This operation consumes ownership of the file descriptor and it will be + /// closed once the object is deallocated. + /// + /// # Example + /// + /// use std::libc; + /// use std::rt::io::pipe; + /// + /// let mut pipe = PipeStream::open(libc::STDERR_FILENO); + /// pipe.write(bytes!("Hello, stderr!")); + /// + /// # Failure + /// + /// If the pipe cannot be created, an error will be raised on the + /// `io_error` condition. + pub fn open(fd: file::fd_t) -> Option { + do with_local_io |io| { + match io.pipe_open(fd) { + Ok(obj) => Some(PipeStream { obj: obj }), + Err(e) => { + io_error::cond.raise(e); + None + } + } + } + } + pub fn new(inner: ~RtioPipe) -> PipeStream { PipeStream { obj: inner } } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 40b509c4bc86..650ef491a3bf 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -322,6 +322,7 @@ mod tests { use path::Path; use run; use str; + use task::spawn; use unstable::running_on_valgrind; use rt::io::native::file; use rt::io::{Writer, Reader}; @@ -394,6 +395,7 @@ mod tests { } #[test] + #[ignore] // FIXME(#10016) cat never sees stdin close fn test_pipes() { let pipe_in = os::pipe(); @@ -412,13 +414,14 @@ mod tests { os::close(pipe_out.out); os::close(pipe_err.out); - let expected = ~"test"; - writeclose(pipe_in.out, expected); + do spawn { + writeclose(pipe_in.out, ~"test"); + } let actual = readclose(pipe_out.input); readclose(pipe_err.input); proc.finish(); - assert_eq!(expected, actual); + assert_eq!(~"test", actual); } fn writeclose(fd: c_int, s: &str) { diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 0e0e52c62737..4ff184b44831 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -18,6 +18,7 @@ use std::libc; use std::run; use std::str; +use std::rt::io; #[test] fn test_destroy_once() { @@ -29,7 +30,9 @@ fn test_destroy_once() { fn test_destroy_twice() { let mut p = run::Process::new("echo", [], run::ProcessOptions::new()); p.destroy(); // this shouldnt crash... - p.destroy(); // ...and nor should this (and nor should the destructor) + do io::io_error::cond.trap(|_| {}).inside { + p.destroy(); // ...and nor should this (and nor should the destructor) + } } fn test_destroy_actually_kills(force: bool) {