Skip to content

Commit d425218

Browse files
committed
Bring io::signal up to date with changes to rt::rtio
1 parent b5a02e0 commit d425218

File tree

3 files changed

+75
-79
lines changed

3 files changed

+75
-79
lines changed

src/libstd/rt/io/signal.rs

+58-35
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,23 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
/*!
12+
13+
Signal handling
14+
15+
This modules provides bindings to receive signals safely, built on top of the
16+
local I/O factory. There are a number of defined signals which can be caught,
17+
but not all signals will work across all platforms (windows doesn't have
18+
definitions for a number of signals.
19+
20+
*/
21+
1122
use comm::{Port, SharedChan, stream};
1223
use hashmap;
1324
use option::{Some, None};
1425
use result::{Err, Ok};
1526
use rt::io::io_error;
16-
use rt::local::Local;
17-
use rt::rtio::{EventLoop, RtioSignalObject};
18-
use rt::sched::Scheduler;
27+
use rt::rtio::{IoFactory, RtioSignal, with_local_io};
1928

2029
#[deriving(Eq, IterBytes)]
2130
pub enum Signum {
@@ -47,19 +56,18 @@ pub enum Signum {
4756
/// Listener automatically unregisters its handles once it is out of scope.
4857
/// However, clients can still unregister signums manually.
4958
///
50-
/// Example usage:
59+
/// # Example
5160
///
5261
/// ```rust
53-
/// use std::rt::io::signal;
54-
/// use std::task;
62+
/// use std::rt::io::signal::{Listener, Interrupt};
5563
///
56-
/// let mut listener = signal::Listener();
64+
/// let mut listener = Listener::new();
5765
/// listener.register(signal::Interrupt);
5866
///
59-
/// do task::spawn {
67+
/// do spawn {
6068
/// loop {
61-
/// match listener.recv() {
62-
/// signal::Interrupt => println("Got Interrupt'ed"),
69+
/// match listener.port.recv() {
70+
/// Interrupt => println("Got Interrupt'ed"),
6371
/// _ => (),
6472
/// }
6573
/// }
@@ -68,15 +76,20 @@ pub enum Signum {
6876
/// ```
6977
pub struct Listener {
7078
/// A map from signums to handles to keep the handles in memory
71-
priv handles: hashmap::HashMap<Signum, ~RtioSignalObject>,
79+
priv handles: hashmap::HashMap<Signum, ~RtioSignal>,
7280
/// chan is where all the handles send signums, which are received by
7381
/// the clients from port.
7482
priv chan: SharedChan<Signum>,
75-
/// Clients of Listener can `recv()` from this port
83+
84+
/// Clients of Listener can `recv()` from this port. This is exposed to
85+
/// allow selection over this port as well as manipulation of the port
86+
/// directly.
7687
port: Port<Signum>,
7788
}
7889

7990
impl Listener {
91+
/// Creates a new listener for signals. Once created, signals are bound via
92+
/// the `register` method (otherwise nothing will ever be received)
8093
pub fn new() -> Listener {
8194
let (port, chan) = stream();
8295
Listener {
@@ -88,33 +101,43 @@ impl Listener {
88101

89102
/// Listen for a signal, returning true when successfully registered for
90103
/// signum. Signals can be received using `recv()`.
104+
///
105+
/// Once a signal is registered, this listener will continue to receive
106+
/// notifications of signals until it is unregistered. This occurs
107+
/// regardless of the number of other listeners registered in other tasks
108+
/// (or on this task).
109+
///
110+
/// Signals are still received if there is no task actively waiting for
111+
/// a signal, and a later call to `recv` will return the signal that was
112+
/// received while no task was waiting on it.
113+
///
114+
/// # Failure
115+
///
116+
/// If this function fails to register a signal handler, then an error will
117+
/// be raised on the `io_error` condition and the function will return
118+
/// false.
91119
pub fn register(&mut self, signum: Signum) -> bool {
92-
match self.handles.find(&signum) {
93-
Some(_) => true, // self is already listening to signum, so succeed
94-
None => {
95-
let chan = self.chan.clone();
96-
let handle = unsafe {
97-
rtdebug!("Listener::register: borrowing io to init UvSignal");
98-
let sched: *mut Scheduler = Local::unsafe_borrow();
99-
rtdebug!("about to init handle");
100-
(*sched).event_loop.signal(signum, chan)
101-
};
102-
match handle {
103-
Ok(w) => {
104-
self.handles.insert(signum, w);
105-
true
106-
},
107-
Err(ioerr) => {
108-
rtdebug!("Listener::register: failed to init: {:?}", ioerr);
109-
io_error::cond.raise(ioerr);
110-
false
111-
},
112-
}
113-
},
120+
if self.handles.contains_key(&signum) {
121+
return true; // self is already listening to signum, so succeed
114122
}
123+
do with_local_io |io| {
124+
match io.signal(signum, self.chan.clone()) {
125+
Ok(w) => {
126+
self.handles.insert(signum, w);
127+
Some(())
128+
},
129+
Err(ioerr) => {
130+
io_error::cond.raise(ioerr);
131+
None
132+
}
133+
}
134+
}.is_some()
115135
}
116136

117-
/// Unregister a signal.
137+
/// Unregisters a signal. If this listener currently had a handler
138+
/// registered for the signal, then it will stop receiving any more
139+
/// notification about the signal. If the signal has already been received,
140+
/// it may still be returned by `recv`.
118141
pub fn unregister(&mut self, signum: Signum) {
119142
self.handles.pop(&signum);
120143
}

src/libstd/rt/uv/signal.rs

+15-42
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@
1010

1111
use cast;
1212
use option::Some;
13-
use libc::{c_int, c_void};
13+
use libc::c_int;
1414
use result::{Err, Ok, Result};
15-
use rt::io::IoError;
1615
use rt::io::signal::Signum;
17-
use rt::uv::{Loop, NativeHandle, NullCallback, SignalCallback, UvError, Watcher};
18-
use rt::uv::uv_error_to_io_error;
16+
use rt::uv::{Loop, NativeHandle, SignalCallback, UvError, Watcher};
1917
use rt::uv::uvll;
2018

2119
pub struct SignalWatcher(*uvll::uv_signal_t);
@@ -34,19 +32,19 @@ impl SignalWatcher {
3432
}
3533
}
3634

37-
pub fn start(&mut self, signum: Signum, callback: SignalCallback) -> Result<(), IoError> {
38-
{
39-
let data = self.get_watcher_data();
40-
data.signal_cb = Some(callback);
41-
}
42-
43-
let ret = unsafe {
44-
uvll::signal_start(self.native_handle(), signal_cb, signum as c_int)
45-
};
46-
47-
return match ret {
48-
0 => Ok(()),
49-
_ => Err(uv_error_to_io_error(UvError(ret))),
35+
pub fn start(&mut self, signum: Signum, callback: SignalCallback)
36+
-> Result<(), UvError>
37+
{
38+
return unsafe {
39+
match uvll::signal_start(self.native_handle(), signal_cb,
40+
signum as c_int) {
41+
0 => {
42+
let data = self.get_watcher_data();
43+
data.signal_cb = Some(callback);
44+
Ok(())
45+
}
46+
n => Err(UvError(n)),
47+
}
5048
};
5149

5250
extern fn signal_cb(handle: *uvll::uv_signal_t, signum: c_int) {
@@ -62,31 +60,6 @@ impl SignalWatcher {
6260
uvll::signal_stop(self.native_handle());
6361
}
6462
}
65-
66-
pub fn close(self, cb: NullCallback) {
67-
let mut watcher = self;
68-
{
69-
let data = watcher.get_watcher_data();
70-
assert!(data.close_cb.is_none());
71-
data.close_cb = Some(cb);
72-
}
73-
74-
unsafe {
75-
uvll::close(watcher.native_handle(), close_cb);
76-
}
77-
78-
extern fn close_cb(handle: *uvll::uv_signal_t) {
79-
let mut watcher: SignalWatcher = NativeHandle::from_native_handle(handle);
80-
{
81-
let data = watcher.get_watcher_data();
82-
data.close_cb.take_unwrap()();
83-
}
84-
watcher.drop_watcher_data();
85-
unsafe {
86-
uvll::free_handle(handle as *c_void);
87-
}
88-
}
89-
}
9063
}
9164

9265
impl NativeHandle<*uvll::uv_signal_t> for SignalWatcher {

src/libstd/rt/uv/uvio.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -865,12 +865,12 @@ impl IoFactory for UvIoFactory {
865865
}
866866

867867
fn signal(&mut self, signum: Signum, channel: SharedChan<Signum>)
868-
-> Result<~RtioSignalObject, IoError> {
868+
-> Result<~RtioSignal, IoError> {
869869
let watcher = SignalWatcher::new(self.uv_loop());
870870
let home = get_handle_to_current_scheduler!();
871871
let mut signal = ~UvSignal::new(watcher, home);
872872
match signal.watcher.start(signum, |_, _| channel.send_deferred(signum)) {
873-
Ok(()) => Ok(signal),
873+
Ok(()) => Ok(signal as ~RtioSignal),
874874
Err(e) => Err(uv_error_to_io_error(e)),
875875
}
876876
}

0 commit comments

Comments
 (0)