Skip to content

Commit 279c351

Browse files
committed
Move stdin to using libuv's pipes instead of a tty
I was seeing a lot of weird behavior with stdin behaving as a tty, and it doesn't really quite make sense, so instead this moves to using libuv's pipes instead (which make more sense for stdin specifically). This prevents piping input to rustc hanging forever.
1 parent 6b70ddf commit 279c351

File tree

9 files changed

+48
-84
lines changed

9 files changed

+48
-84
lines changed

src/libstd/rt/io/file.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ on a `ToCStr` object. This trait is already defined for common
1919
objects such as strings and `Path` instances.
2020
2121
All operations in this module, including those as part of `FileStream` et al
22-
block the task during execution. Most will raise `std::rt::io::{io_error,io_error}`
22+
block the task during execution. Most will raise `std::rt::io::io_error`
2323
conditions in the event of failure.
2424
2525
Also included in this module are the `FileInfo` and `DirectoryInfo` traits. When

src/libstd/rt/io/net/unix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub struct UnixStream {
3737

3838
impl UnixStream {
3939
fn new(obj: ~RtioPipe) -> UnixStream {
40-
UnixStream { obj: PipeStream::new_bound(obj) }
40+
UnixStream { obj: PipeStream::new(obj) }
4141
}
4242

4343
/// Connect to a pipe named by `path`. This will attempt to open a

src/libstd/rt/io/pipe.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub struct PipeStream {
2323
}
2424

2525
impl PipeStream {
26-
pub fn new_bound(inner: ~RtioPipe) -> PipeStream {
26+
pub fn new(inner: ~RtioPipe) -> PipeStream {
2727
PipeStream { obj: inner }
2828
}
2929
}
@@ -42,7 +42,7 @@ impl Reader for PipeStream {
4242
}
4343
}
4444

45-
fn eof(&mut self) -> bool { fail!() }
45+
fn eof(&mut self) -> bool { false }
4646
}
4747

4848
impl Writer for PipeStream {
@@ -55,5 +55,5 @@ impl Writer for PipeStream {
5555
}
5656
}
5757

58-
fn flush(&mut self) { fail!() }
58+
fn flush(&mut self) {}
5959
}

src/libstd/rt/io/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl Process {
8989
Ok((p, io)) => Some(Process{
9090
handle: p,
9191
io: io.move_iter().map(|p|
92-
p.map(|p| io::PipeStream::new_bound(p))
92+
p.map(|p| io::PipeStream::new(p))
9393
).collect()
9494
}),
9595
Err(ioerr) => {

src/libstd/rt/io/stdio.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use fmt;
3030
use libc;
3131
use option::{Option, Some, None};
3232
use result::{Ok, Err};
33-
use rt::rtio::{IoFactory, RtioTTY, with_local_io};
33+
use rt::rtio::{IoFactory, RtioTTY, with_local_io, RtioPipe};
3434
use super::{Reader, Writer, io_error};
3535

3636
#[fixed_stack_segment] #[inline(never)]
@@ -52,8 +52,17 @@ fn tty<T>(fd: libc::c_int, f: &fn(~RtioTTY) -> T) -> T {
5252
/// Creates a new non-blocking handle to the stdin of the current process.
5353
///
5454
/// See `stdout()` for notes about this function.
55+
#[fixed_stack_segment] #[inline(never)]
5556
pub fn stdin() -> StdReader {
56-
do tty(libc::STDIN_FILENO) |tty| { StdReader { inner: tty } }
57+
do with_local_io |io| {
58+
match io.pipe_open(unsafe { libc::dup(libc::STDIN_FILENO) }) {
59+
Ok(stream) => Some(StdReader { inner: stream }),
60+
Err(e) => {
61+
io_error::cond.raise(e);
62+
None
63+
}
64+
}
65+
}.unwrap()
5766
}
5867

5968
/// Creates a new non-blocking handle to the stdout of the current process.
@@ -108,28 +117,7 @@ pub fn println_args(fmt: &fmt::Arguments) {
108117

109118
/// Representation of a reader of a standard input stream
110119
pub struct StdReader {
111-
priv inner: ~RtioTTY
112-
}
113-
114-
impl StdReader {
115-
/// Controls whether this output stream is a "raw stream" or simply a normal
116-
/// stream.
117-
///
118-
/// # Failure
119-
///
120-
/// This function will raise on the `io_error` condition if an error
121-
/// happens.
122-
pub fn set_raw(&mut self, raw: bool) {
123-
match self.inner.set_raw(raw) {
124-
Ok(()) => {},
125-
Err(e) => io_error::cond.raise(e),
126-
}
127-
}
128-
129-
/// Returns whether this tream is attached to a TTY instance or not.
130-
///
131-
/// This is similar to libc's isatty() function
132-
pub fn isatty(&self) -> bool { self.inner.isatty() }
120+
priv inner: ~RtioPipe
133121
}
134122

135123
impl Reader for StdReader {

src/libstd/rt/rtio.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ pub trait IoFactory {
9494
fn spawn(&mut self, config: ProcessConfig)
9595
-> Result<(~RtioProcess, ~[Option<~RtioPipe>]), IoError>;
9696

97+
fn pipe_open(&mut self, fd: c_int) -> Result<~RtioPipe, IoError>;
9798
fn unix_bind(&mut self, path: &CString) ->
9899
Result<~RtioUnixListener, IoError>;
99100
fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError>;

src/libstd/rt/uv/net.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl StreamWatcher {
159159
// but read_stop may be called from inside one of them and we
160160
// would end up freeing the in-use environment
161161
let handle = self.native_handle();
162-
unsafe { uvll::read_stop(handle); }
162+
unsafe { assert_eq!(uvll::read_stop(handle), 0); }
163163
}
164164

165165
pub fn write(&mut self, buf: Buf, cb: ConnectionCallback) {

src/libstd/rt/uv/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ unsafe fn set_stdio(dst: *uvll::uv_stdio_container_t,
146146
if writable {
147147
flags |= uvll::STDIO_WRITABLE_PIPE as libc::c_int;
148148
}
149-
let pipe = UvUnboundPipe::new_fresh(loop_);
149+
let pipe = UvUnboundPipe::new(loop_);
150150
let handle = pipe.pipe.as_stream().native_handle();
151151
uvll::set_stdio_container_flags(dst, flags);
152152
uvll::set_stdio_container_stream(dst, handle);

src/libstd/rt/uv/uvio.rs

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -805,47 +805,32 @@ impl IoFactory for UvIoFactory {
805805

806806
fn unix_bind(&mut self, path: &CString) ->
807807
Result<~RtioUnixListener, IoError> {
808-
let mut pipe = Pipe::new(self.uv_loop(), false);
809-
match pipe.bind(path) {
810-
Ok(()) => {
811-
let handle = get_handle_to_current_scheduler!();
812-
let pipe = UvUnboundPipe::new(pipe, handle);
813-
Ok(~UvUnixListener::new(pipe) as ~RtioUnixListener)
814-
}
815-
Err(e) => {
816-
let scheduler: ~Scheduler = Local::take();
817-
do scheduler.deschedule_running_task_and_then |_, task| {
818-
let task_cell = Cell::new(task);
819-
do pipe.close {
820-
let scheduler: ~Scheduler = Local::take();
821-
scheduler.resume_blocked_task_immediately(
822-
task_cell.take());
823-
}
824-
}
825-
Err(uv_error_to_io_error(e))
826-
}
808+
let mut pipe = UvUnboundPipe::new(self.uv_loop());
809+
match pipe.pipe.bind(path) {
810+
Ok(()) => Ok(~UvUnixListener::new(pipe) as ~RtioUnixListener),
811+
Err(e) => Err(uv_error_to_io_error(e)),
827812
}
828813
}
829814

830815
fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError> {
831-
let scheduler: ~Scheduler = Local::take();
832-
let mut pipe = Pipe::new(self.uv_loop(), false);
816+
let pipe = UvUnboundPipe::new(self.uv_loop());
817+
let mut rawpipe = pipe.pipe;
818+
833819
let result_cell = Cell::new_empty();
834820
let result_cell_ptr: *Cell<Result<~RtioPipe, IoError>> = &result_cell;
821+
let pipe_cell = Cell::new(pipe);
822+
let pipe_cell_ptr: *Cell<UvUnboundPipe> = &pipe_cell;
835823

824+
let scheduler: ~Scheduler = Local::take();
836825
do scheduler.deschedule_running_task_and_then |_, task| {
837826
let task_cell = Cell::new(task);
838-
do pipe.connect(path) |stream, err| {
827+
do rawpipe.connect(path) |_stream, err| {
839828
let res = match err {
840829
None => {
841-
let handle = stream.native_handle();
842-
let pipe = NativeHandle::from_native_handle(
843-
handle as *uvll::uv_pipe_t);
844-
let home = get_handle_to_current_scheduler!();
845-
let pipe = UvUnboundPipe::new(pipe, home);
830+
let pipe = unsafe { (*pipe_cell_ptr).take() };
846831
Ok(~UvPipeStream::new(pipe) as ~RtioPipe)
847832
}
848-
Some(e) => { Err(uv_error_to_io_error(e)) }
833+
Some(e) => Err(uv_error_to_io_error(e)),
849834
};
850835
unsafe { (*result_cell_ptr).put_back(res); }
851836
let scheduler: ~Scheduler = Local::take();
@@ -854,18 +839,7 @@ impl IoFactory for UvIoFactory {
854839
}
855840

856841
assert!(!result_cell.is_empty());
857-
let ret = result_cell.take();
858-
if ret.is_err() {
859-
let scheduler: ~Scheduler = Local::take();
860-
do scheduler.deschedule_running_task_and_then |_, task| {
861-
let task_cell = Cell::new(task);
862-
do pipe.close {
863-
let scheduler: ~Scheduler = Local::take();
864-
scheduler.resume_blocked_task_immediately(task_cell.take());
865-
}
866-
}
867-
}
868-
return ret;
842+
return result_cell.take();
869843
}
870844

871845
fn tty_open(&mut self, fd: c_int, readable: bool)
@@ -879,6 +853,14 @@ impl IoFactory for UvIoFactory {
879853
Err(e) => Err(uv_error_to_io_error(e))
880854
}
881855
}
856+
857+
fn pipe_open(&mut self, fd: c_int) -> Result<~RtioPipe, IoError> {
858+
let mut pipe = UvUnboundPipe::new(self.uv_loop());
859+
match pipe.pipe.open(fd) {
860+
Ok(()) => Ok(~UvPipeStream::new(pipe) as ~RtioPipe),
861+
Err(e) => Err(uv_error_to_io_error(e))
862+
}
863+
}
882864
}
883865

884866
pub struct UvTcpListener {
@@ -1075,14 +1057,9 @@ pub struct UvUnboundPipe {
10751057
}
10761058

10771059
impl UvUnboundPipe {
1078-
/// Takes ownership of an unbound pipe along with the scheduler that it is
1079-
/// homed on.
1080-
fn new(pipe: Pipe, home: SchedHandle) -> UvUnboundPipe {
1081-
UvUnboundPipe { pipe: pipe, home: home }
1082-
}
1083-
1084-
/// Creates a fresh new unbound pipe on the specified I/O loop
1085-
pub fn new_fresh(loop_: &Loop) -> UvUnboundPipe {
1060+
/// Creates a new unbound pipe homed to the current scheduler, placed on the
1061+
/// specified event loop
1062+
pub fn new(loop_: &Loop) -> UvUnboundPipe {
10861063
UvUnboundPipe {
10871064
pipe: Pipe::new(loop_, false),
10881065
home: get_handle_to_current_scheduler!(),
@@ -1727,10 +1704,8 @@ impl RtioUnixListener for UvUnixListener {
17271704
let inc = match status {
17281705
Some(e) => Err(uv_error_to_io_error(e)),
17291706
None => {
1730-
let inc = Pipe::new(&server.event_loop(), false);
1731-
server.accept(inc.as_stream());
1732-
let home = get_handle_to_current_scheduler!();
1733-
let pipe = UvUnboundPipe::new(inc, home);
1707+
let pipe = UvUnboundPipe::new(&server.event_loop());
1708+
server.accept(pipe.pipe.as_stream());
17341709
Ok(~UvPipeStream::new(pipe) as ~RtioPipe)
17351710
}
17361711
};

0 commit comments

Comments
 (0)