diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-10-16 11:47:12 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-10-24 14:21:57 -0700 |
| commit | 35756fbcf6572d588929fde64fb4027f47e9d0af (patch) | |
| tree | 8a2f0ec01c2eb26f5db34887b8b2335a844d5b9d /src/libstd/rt/uv/uvio.rs | |
| parent | 32b07c6a40bd7e1874244096f413096a6e059a29 (diff) | |
| download | rust-35756fbcf6572d588929fde64fb4027f47e9d0af.tar.gz rust-35756fbcf6572d588929fde64fb4027f47e9d0af.zip | |
Move rt::io::stdio from FileStream to a TTY
We get a little more functionality from libuv for these kinds of streams (things like terminal dimentions), and it also appears to more gracefully handle the stream being a window. Beforehand, if you used stdio and hit CTRL+d on a process, libuv would continually return 0-length successful reads instead of interpreting that the stream was closed. I was hoping to be able to write tests for this, but currently the testing infrastructure doesn't allow tests with a stdin and a stdout, but this has been manually tested! (not that it means much)
Diffstat (limited to 'src/libstd/rt/uv/uvio.rs')
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index db19bc7463a..f1a5916ee13 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -869,6 +869,18 @@ impl IoFactory for UvIoFactory { } return ret; } + + fn tty_open(&mut self, fd: c_int, readable: bool, close_on_drop: bool) + -> Result<~RtioTTYObject, IoError> { + match tty::TTY::new(self.uv_loop(), fd, readable) { + Ok(tty) => Ok(~UvTTY { + home: get_handle_to_current_scheduler!(), + tty: tty, + close_on_drop: close_on_drop, + }), + Err(e) => Err(uv_error_to_io_error(e)) + } + } } pub struct UvTcpListener { @@ -1734,6 +1746,34 @@ impl RtioUnixListener for UvUnixListener { } } +pub struct UvTTY { + tty: tty::TTY, + home: SchedHandle, + close_on_drop: bool, +} + +impl HomingIO for UvTTY { + fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home } +} + +impl Drop for UvTTY { + fn drop(&mut self) { + if self.close_on_drop { + let scheduler: ~Scheduler = Local::take(); + do scheduler.deschedule_running_task_and_then |_, task| { + let task = Cell::new(task); + do self.tty.close { + let scheduler: ~Scheduler = Local::take(); + scheduler.resume_blocked_task_immediately(task.take()); + } + } + } else { + self.tty.drop_watcher_data(); + unsafe { uvll::free_handle(self.tty.native_handle()) } + } + } +} + pub struct UvUnixAcceptor { listener: UvUnixListener, incoming: Tube<Result<~RtioPipeObject, IoError>>, @@ -1769,6 +1809,40 @@ impl RtioUnixAcceptor for UvUnixAcceptor { } } +impl RtioTTY for UvTTY { + fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> { + do self.home_for_io_with_sched |self_, scheduler| { + read_stream(self_.tty.as_stream(), scheduler, buf) + } + } + + fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { + do self.home_for_io_with_sched |self_, scheduler| { + write_stream(self_.tty.as_stream(), scheduler, buf) + } + } + + fn set_raw(&mut self, raw: bool) -> Result<(), IoError> { + do self.home_for_io |self_| { + match self_.tty.set_mode(raw) { + Ok(p) => Ok(p), Err(e) => Err(uv_error_to_io_error(e)) + } + } + } + + fn reset_mode(&mut self) { + do self.home_for_io |self_| { self_.tty.reset_mode() } + } + + fn get_winsize(&mut self) -> Result<(int, int), IoError> { + do self.home_for_io |self_| { + match self_.tty.get_winsize() { + Ok(p) => Ok(p), Err(e) => Err(uv_error_to_io_error(e)) + } + } + } +} + #[test] fn test_simple_io_no_connect() { do run_in_mt_newsched_task { |
