diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-10-22 08:51:44 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-10-24 14:22:35 -0700 |
| commit | d425218395b4a4dd7c6e4f3d680447efd2a3abc6 (patch) | |
| tree | 2fe3e4bd7ea85a77fa5213e2e1d7377df5fc1183 /src/libstd | |
| parent | b5a02e07845b9fb4bc9b09909bd996c874fa3eed (diff) | |
| download | rust-d425218395b4a4dd7c6e4f3d680447efd2a3abc6.tar.gz rust-d425218395b4a4dd7c6e4f3d680447efd2a3abc6.zip | |
Bring io::signal up to date with changes to rt::rtio
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/rt/io/signal.rs | 93 | ||||
| -rw-r--r-- | src/libstd/rt/uv/signal.rs | 57 | ||||
| -rw-r--r-- | src/libstd/rt/uv/uvio.rs | 4 |
3 files changed, 75 insertions, 79 deletions
diff --git a/src/libstd/rt/io/signal.rs b/src/libstd/rt/io/signal.rs index d3c260d361c..07fe91f57a0 100644 --- a/src/libstd/rt/io/signal.rs +++ b/src/libstd/rt/io/signal.rs @@ -8,14 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! + +Signal handling + +This modules provides bindings to receive signals safely, built on top of the +local I/O factory. There are a number of defined signals which can be caught, +but not all signals will work across all platforms (windows doesn't have +definitions for a number of signals. + +*/ + use comm::{Port, SharedChan, stream}; use hashmap; use option::{Some, None}; use result::{Err, Ok}; use rt::io::io_error; -use rt::local::Local; -use rt::rtio::{EventLoop, RtioSignalObject}; -use rt::sched::Scheduler; +use rt::rtio::{IoFactory, RtioSignal, with_local_io}; #[deriving(Eq, IterBytes)] pub enum Signum { @@ -47,19 +56,18 @@ pub enum Signum { /// Listener automatically unregisters its handles once it is out of scope. /// However, clients can still unregister signums manually. /// -/// Example usage: +/// # Example /// /// ```rust -/// use std::rt::io::signal; -/// use std::task; +/// use std::rt::io::signal::{Listener, Interrupt}; /// -/// let mut listener = signal::Listener(); +/// let mut listener = Listener::new(); /// listener.register(signal::Interrupt); /// -/// do task::spawn { +/// do spawn { /// loop { -/// match listener.recv() { -/// signal::Interrupt => println("Got Interrupt'ed"), +/// match listener.port.recv() { +/// Interrupt => println("Got Interrupt'ed"), /// _ => (), /// } /// } @@ -68,15 +76,20 @@ pub enum Signum { /// ``` pub struct Listener { /// A map from signums to handles to keep the handles in memory - priv handles: hashmap::HashMap<Signum, ~RtioSignalObject>, + priv handles: hashmap::HashMap<Signum, ~RtioSignal>, /// chan is where all the handles send signums, which are received by /// the clients from port. priv chan: SharedChan<Signum>, - /// Clients of Listener can `recv()` from this port + + /// Clients of Listener can `recv()` from this port. This is exposed to + /// allow selection over this port as well as manipulation of the port + /// directly. port: Port<Signum>, } impl Listener { + /// Creates a new listener for signals. Once created, signals are bound via + /// the `register` method (otherwise nothing will ever be received) pub fn new() -> Listener { let (port, chan) = stream(); Listener { @@ -88,33 +101,43 @@ impl Listener { /// Listen for a signal, returning true when successfully registered for /// signum. Signals can be received using `recv()`. + /// + /// Once a signal is registered, this listener will continue to receive + /// notifications of signals until it is unregistered. This occurs + /// regardless of the number of other listeners registered in other tasks + /// (or on this task). + /// + /// Signals are still received if there is no task actively waiting for + /// a signal, and a later call to `recv` will return the signal that was + /// received while no task was waiting on it. + /// + /// # Failure + /// + /// If this function fails to register a signal handler, then an error will + /// be raised on the `io_error` condition and the function will return + /// false. pub fn register(&mut self, signum: Signum) -> bool { - match self.handles.find(&signum) { - Some(_) => true, // self is already listening to signum, so succeed - None => { - let chan = self.chan.clone(); - let handle = unsafe { - rtdebug!("Listener::register: borrowing io to init UvSignal"); - let sched: *mut Scheduler = Local::unsafe_borrow(); - rtdebug!("about to init handle"); - (*sched).event_loop.signal(signum, chan) - }; - match handle { - Ok(w) => { - self.handles.insert(signum, w); - true - }, - Err(ioerr) => { - rtdebug!("Listener::register: failed to init: {:?}", ioerr); - io_error::cond.raise(ioerr); - false - }, - } - }, + if self.handles.contains_key(&signum) { + return true; // self is already listening to signum, so succeed } + do with_local_io |io| { + match io.signal(signum, self.chan.clone()) { + Ok(w) => { + self.handles.insert(signum, w); + Some(()) + }, + Err(ioerr) => { + io_error::cond.raise(ioerr); + None + } + } + }.is_some() } - /// Unregister a signal. + /// Unregisters a signal. If this listener currently had a handler + /// registered for the signal, then it will stop receiving any more + /// notification about the signal. If the signal has already been received, + /// it may still be returned by `recv`. pub fn unregister(&mut self, signum: Signum) { self.handles.pop(&signum); } diff --git a/src/libstd/rt/uv/signal.rs b/src/libstd/rt/uv/signal.rs index 70ea8e399d5..e51b7d90d95 100644 --- a/src/libstd/rt/uv/signal.rs +++ b/src/libstd/rt/uv/signal.rs @@ -10,12 +10,10 @@ use cast; use option::Some; -use libc::{c_int, c_void}; +use libc::c_int; use result::{Err, Ok, Result}; -use rt::io::IoError; use rt::io::signal::Signum; -use rt::uv::{Loop, NativeHandle, NullCallback, SignalCallback, UvError, Watcher}; -use rt::uv::uv_error_to_io_error; +use rt::uv::{Loop, NativeHandle, SignalCallback, UvError, Watcher}; use rt::uv::uvll; pub struct SignalWatcher(*uvll::uv_signal_t); @@ -34,19 +32,19 @@ impl SignalWatcher { } } - pub fn start(&mut self, signum: Signum, callback: SignalCallback) -> Result<(), IoError> { - { - let data = self.get_watcher_data(); - data.signal_cb = Some(callback); - } - - let ret = unsafe { - uvll::signal_start(self.native_handle(), signal_cb, signum as c_int) - }; - - return match ret { - 0 => Ok(()), - _ => Err(uv_error_to_io_error(UvError(ret))), + pub fn start(&mut self, signum: Signum, callback: SignalCallback) + -> Result<(), UvError> + { + return unsafe { + match uvll::signal_start(self.native_handle(), signal_cb, + signum as c_int) { + 0 => { + let data = self.get_watcher_data(); + data.signal_cb = Some(callback); + Ok(()) + } + n => Err(UvError(n)), + } }; extern fn signal_cb(handle: *uvll::uv_signal_t, signum: c_int) { @@ -62,31 +60,6 @@ impl SignalWatcher { uvll::signal_stop(self.native_handle()); } } - - pub fn close(self, cb: NullCallback) { - let mut watcher = self; - { - let data = watcher.get_watcher_data(); - assert!(data.close_cb.is_none()); - data.close_cb = Some(cb); - } - - unsafe { - uvll::close(watcher.native_handle(), close_cb); - } - - extern fn close_cb(handle: *uvll::uv_signal_t) { - let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle); - { - let data = watcher.get_watcher_data(); - data.close_cb.take_unwrap()(); - } - watcher.drop_watcher_data(); - unsafe { - uvll::free_handle(handle as *c_void); - } - } - } } impl NativeHandle<*uvll::uv_signal_t> for SignalWatcher { diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 48f4dbe43d6..473eec32c67 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -865,12 +865,12 @@ impl IoFactory for UvIoFactory { } fn signal(&mut self, signum: Signum, channel: SharedChan<Signum>) - -> Result<~RtioSignalObject, IoError> { + -> Result<~RtioSignal, IoError> { let watcher = SignalWatcher::new(self.uv_loop()); let home = get_handle_to_current_scheduler!(); let mut signal = ~UvSignal::new(watcher, home); match signal.watcher.start(signum, |_, _| channel.send_deferred(signum)) { - Ok(()) => Ok(signal), + Ok(()) => Ok(signal as ~RtioSignal), Err(e) => Err(uv_error_to_io_error(e)), } } |
