]> git.lizzy.rs Git - rust.git/commitdiff
Bring io::signal up to date with changes to rt::rtio
authorAlex Crichton <alex@alexcrichton.com>
Tue, 22 Oct 2013 15:51:44 +0000 (08:51 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 24 Oct 2013 21:22:35 +0000 (14:22 -0700)
src/libstd/rt/io/signal.rs
src/libstd/rt/uv/signal.rs
src/libstd/rt/uv/uvio.rs

index d3c260d361c63da63c158726dac29b855a0a2864..07fe91f57a0d90720755ada25fe9567c130f39b8 100644 (file)
@@ -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 @@ pub fn new() -> 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);
     }
index 70ea8e399d587074282c61c1b41d207552e5dc30..e51b7d90d95507e3205237a1f83ae7bf4635a6e9 100644 (file)
 
 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 @@ pub fn new(loop_: &mut Loop) -> 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 @@ pub fn stop(&mut self) {
             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 {
index 48f4dbe43d6f4f0e2d3340bc3e008fd5287ed613..473eec32c67eb4e28147b93d93336ad2c3e54f1d 100644 (file)
@@ -865,12 +865,12 @@ fn pipe_open(&mut self, fd: c_int) -> Result<~RtioPipe, IoError> {
     }
 
     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)),
         }
     }