diff options
Diffstat (limited to 'src/libstd/rt/uv')
| -rw-r--r-- | src/libstd/rt/uv/mod.rs | 11 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 86 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvll.rs | 5 |
3 files changed, 58 insertions, 44 deletions
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs index a03264af7e1..18c99157707 100644 --- a/src/libstd/rt/uv/mod.rs +++ b/src/libstd/rt/uv/mod.rs @@ -170,6 +170,7 @@ pub trait WatcherInterop { fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData; fn drop_watcher_data(&mut self); fn close(self, cb: NullCallback); + fn close_async(self); } impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W { @@ -235,6 +236,16 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W { unsafe { uvll::free_handle(handle as *c_void) } } } + + fn close_async(self) { + unsafe { uvll::close(self.native_handle(), close_cb); } + + extern fn close_cb(handle: *uvll::uv_handle_t) { + let mut h: Handle = NativeHandle::from_native_handle(handle); + h.drop_watcher_data(); + unsafe { uvll::free_handle(handle as *c_void) } + } + } } // XXX: Need to define the error constants like EOF so they can be diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 322588973ae..915c7d0da52 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -868,13 +868,13 @@ impl IoFactory for UvIoFactory { return ret; } - fn tty_open(&mut self, fd: c_int, readable: bool, close_on_drop: bool) + fn tty_open(&mut self, fd: c_int, readable: bool) -> Result<~RtioTTY, 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, + fd: fd, } as ~RtioTTY), Err(e) => Err(uv_error_to_io_error(e)) } @@ -1748,7 +1748,7 @@ impl RtioUnixListener for UvUnixListener { pub struct UvTTY { tty: tty::TTY, home: SchedHandle, - close_on_drop: bool, + fd: c_int, } impl HomingIO for UvTTY { @@ -1757,20 +1757,48 @@ impl HomingIO for UvTTY { 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()); - } + // TTY handles are used for the logger in a task, so this destructor is + // run when a task is destroyed. When a task is being destroyed, a local + // scheduler isn't available, so we can't do the normal "take the + // scheduler and resume once close is done". Instead close operations on + // a TTY are asynchronous. + + self.tty.close_async(); + } +} + +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)) } - } else { - self.tty.drop_watcher_data(); - unsafe { uvll::free_handle(self.tty.native_handle()) } } } + + 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)) + } + } + } + + fn isatty(&self) -> bool { + unsafe { uvll::guess_handle(self.fd) == uvll::UV_TTY } + } } pub struct UvUnixAcceptor { @@ -1808,36 +1836,6 @@ 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 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)) - } - } - } -} - // this function is full of lies unsafe fn local_io() -> &'static mut IoFactory { do Local::borrow |sched: &mut Scheduler| { diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs index e78b2579779..8f8aea9d121 100644 --- a/src/libstd/rt/uv/uvll.rs +++ b/src/libstd/rt/uv/uvll.rs @@ -986,6 +986,10 @@ pub unsafe fn tty_get_winsize(tty: *uv_tty_t, width: *c_int, #[fixed_stack_segment]; #[inline(never)]; rust_uv_tty_get_winsize(tty, width, height) } +pub unsafe fn guess_handle(fd: c_int) -> uv_handle_type { + #[fixed_stack_segment]; #[inline(never)]; + rust_uv_guess_handle(fd) +} pub struct uv_err_data { priv err_name: ~str, @@ -1140,6 +1144,7 @@ extern { fn rust_uv_tty_set_mode(tty: *uv_tty_t, mode: c_int) -> c_int; fn rust_uv_tty_get_winsize(tty: *uv_tty_t, width: *c_int, height: *c_int) -> c_int; + fn rust_uv_guess_handle(fd: c_int) -> uv_handle_type; // These should all really be constants... #[rust_stack] pub fn rust_SOCK_STREAM() -> c_int; |
