Remove std::io::signal
The `std::io::signal` API was only implemented under `librustuv`, which is now being removed. Rather than keep around an unimplemented API, this commit removes it altogether. See the [runtime removal RFC](https://github.com/rust-lang/rfcs/pull/230) for more context. See [green-rs](https://github.com/alexcrichton/green-rs/) for a possible migration path for signal handling code, although in the long run we plan to add native signal handling to `std::io`. [breaking-change]
This commit is contained in:
parent
c5d2ed54a3
commit
dad59bdcbc
2 changed files with 1 additions and 238 deletions
|
@ -21,7 +21,7 @@
|
||||||
`std::io` provides Rust's basic I/O types,
|
`std::io` provides Rust's basic I/O types,
|
||||||
for reading and writing to files, TCP, UDP,
|
for reading and writing to files, TCP, UDP,
|
||||||
and other types of sockets and pipes,
|
and other types of sockets and pipes,
|
||||||
manipulating the file system, spawning processes and signal handling.
|
manipulating the file system, spawning processes.
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
|
@ -275,7 +275,6 @@ pub mod fs;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
pub mod pipe;
|
pub mod pipe;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod signal;
|
|
||||||
pub mod stdio;
|
pub mod stdio;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
|
@ -1,236 +0,0 @@
|
||||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// 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 clone::Clone;
|
|
||||||
use collections::MutableSeq;
|
|
||||||
use comm::{Sender, Receiver, channel};
|
|
||||||
use io;
|
|
||||||
use iter::Iterator;
|
|
||||||
use kinds::Send;
|
|
||||||
use mem::drop;
|
|
||||||
use option::{Some, None};
|
|
||||||
use boxed::Box;
|
|
||||||
use result::{Ok, Err};
|
|
||||||
use rt::rtio::{IoFactory, LocalIo, RtioSignal, Callback};
|
|
||||||
use slice::ImmutableSlice;
|
|
||||||
use vec::Vec;
|
|
||||||
|
|
||||||
/// Signals that can be sent and received
|
|
||||||
#[repr(int)]
|
|
||||||
#[deriving(PartialEq, Hash, Show)]
|
|
||||||
pub enum Signum {
|
|
||||||
/// Equivalent to SIGBREAK, delivered when the user presses Ctrl-Break.
|
|
||||||
Break = 21i,
|
|
||||||
/// Equivalent to SIGHUP, delivered when the user closes the terminal
|
|
||||||
/// window. On delivery of HangUp, the program is given approximately
|
|
||||||
/// 10 seconds to perform any cleanup. After that, Windows will
|
|
||||||
/// unconditionally terminate it.
|
|
||||||
HangUp = 1i,
|
|
||||||
/// Equivalent to SIGINT, delivered when the user presses Ctrl-c.
|
|
||||||
Interrupt = 2i,
|
|
||||||
/// Equivalent to SIGQUIT, delivered when the user presses Ctrl-\.
|
|
||||||
Quit = 3i,
|
|
||||||
/// Equivalent to SIGTSTP, delivered when the user presses Ctrl-z.
|
|
||||||
StopTemporarily = 20i,
|
|
||||||
/// Equivalent to SIGUSR1.
|
|
||||||
User1 = 10i,
|
|
||||||
/// Equivalent to SIGUSR2.
|
|
||||||
User2 = 12i,
|
|
||||||
/// Equivalent to SIGWINCH, delivered when the console has been resized.
|
|
||||||
/// WindowSizeChange may not be delivered in a timely manner; size change
|
|
||||||
/// will only be detected when the cursor is being moved.
|
|
||||||
WindowSizeChange = 28i,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Listener provides a receiver to listen for registered signals.
|
|
||||||
///
|
|
||||||
/// Listener automatically unregisters its handles once it is out of scope.
|
|
||||||
/// However, clients can still unregister signums manually.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust,no_run
|
|
||||||
/// # #![allow(unused_must_use)]
|
|
||||||
/// use std::io::signal::{Listener, Interrupt};
|
|
||||||
///
|
|
||||||
/// let mut listener = Listener::new();
|
|
||||||
/// listener.register(Interrupt);
|
|
||||||
///
|
|
||||||
/// loop {
|
|
||||||
/// match listener.rx.recv() {
|
|
||||||
/// Interrupt => println!("Got Interrupt'ed"),
|
|
||||||
/// _ => (),
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub struct Listener {
|
|
||||||
/// A map from signums to handles to keep the handles in memory
|
|
||||||
handles: Vec<(Signum, Box<RtioSignal + Send>)>,
|
|
||||||
/// This is where all the handles send signums, which are received by
|
|
||||||
/// the clients from the receiver.
|
|
||||||
tx: Sender<Signum>,
|
|
||||||
|
|
||||||
/// Clients of Listener can `recv()` on this receiver. This is exposed to
|
|
||||||
/// allow selection over it as well as manipulation of the receiver
|
|
||||||
/// directly.
|
|
||||||
pub rx: Receiver<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 (tx, rx) = channel();
|
|
||||||
Listener {
|
|
||||||
tx: tx,
|
|
||||||
rx: rx,
|
|
||||||
handles: vec!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
///
|
|
||||||
/// # Error
|
|
||||||
///
|
|
||||||
/// If this function fails to register a signal handler, then an error will
|
|
||||||
/// be returned.
|
|
||||||
pub fn register(&mut self, signum: Signum) -> io::IoResult<()> {
|
|
||||||
struct SignalCallback {
|
|
||||||
signum: Signum,
|
|
||||||
tx: Sender<Signum>,
|
|
||||||
}
|
|
||||||
impl Callback for SignalCallback {
|
|
||||||
fn call(&mut self) { self.tx.send(self.signum) }
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.handles.iter().any(|&(sig, _)| sig == signum) {
|
|
||||||
return Ok(()); // self is already listening to signum, so succeed
|
|
||||||
}
|
|
||||||
match LocalIo::maybe_raise(|io| {
|
|
||||||
io.signal(signum as int, box SignalCallback {
|
|
||||||
signum: signum,
|
|
||||||
tx: self.tx.clone(),
|
|
||||||
})
|
|
||||||
}) {
|
|
||||||
Ok(handle) => {
|
|
||||||
self.handles.push((signum, handle));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Err(e) => Err(io::IoError::from_rtio_error(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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) {
|
|
||||||
match self.handles.iter().position(|&(i, _)| i == signum) {
|
|
||||||
Some(i) => drop(self.handles.remove(i)),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(test, unix))]
|
|
||||||
mod test_unix {
|
|
||||||
use prelude::*;
|
|
||||||
use libc;
|
|
||||||
use comm::Empty;
|
|
||||||
use io::timer;
|
|
||||||
use super::{Listener, Interrupt};
|
|
||||||
use time::Duration;
|
|
||||||
|
|
||||||
fn sigint() {
|
|
||||||
unsafe {
|
|
||||||
libc::funcs::posix88::signal::kill(libc::getpid(), libc::SIGINT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test] #[cfg(not(target_os="android"))] // FIXME(#10378)
|
|
||||||
fn test_io_signal_smoketest() {
|
|
||||||
let mut signal = Listener::new();
|
|
||||||
signal.register(Interrupt).unwrap();
|
|
||||||
sigint();
|
|
||||||
timer::sleep(Duration::milliseconds(10));
|
|
||||||
match signal.rx.recv() {
|
|
||||||
Interrupt => (),
|
|
||||||
s => fail!("Expected Interrupt, got {:?}", s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test] #[cfg(not(target_os="android"))] // FIXME(#10378)
|
|
||||||
fn test_io_signal_two_signal_one_signum() {
|
|
||||||
let mut s1 = Listener::new();
|
|
||||||
let mut s2 = Listener::new();
|
|
||||||
s1.register(Interrupt).unwrap();
|
|
||||||
s2.register(Interrupt).unwrap();
|
|
||||||
sigint();
|
|
||||||
timer::sleep(Duration::milliseconds(10));
|
|
||||||
match s1.rx.recv() {
|
|
||||||
Interrupt => (),
|
|
||||||
s => fail!("Expected Interrupt, got {:?}", s),
|
|
||||||
}
|
|
||||||
match s2.rx.recv() {
|
|
||||||
Interrupt => (),
|
|
||||||
s => fail!("Expected Interrupt, got {:?}", s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test] #[cfg(not(target_os="android"))] // FIXME(#10378)
|
|
||||||
fn test_io_signal_unregister() {
|
|
||||||
let mut s1 = Listener::new();
|
|
||||||
let mut s2 = Listener::new();
|
|
||||||
s1.register(Interrupt).unwrap();
|
|
||||||
s2.register(Interrupt).unwrap();
|
|
||||||
s2.unregister(Interrupt);
|
|
||||||
sigint();
|
|
||||||
timer::sleep(Duration::milliseconds(10));
|
|
||||||
assert_eq!(s2.rx.try_recv(), Err(Empty));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(test, windows))]
|
|
||||||
mod test_windows {
|
|
||||||
use super::{User1, Listener};
|
|
||||||
use result::{Ok, Err};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_io_signal_invalid_signum() {
|
|
||||||
let mut s = Listener::new();
|
|
||||||
match s.register(User1) {
|
|
||||||
Ok(..) => {
|
|
||||||
fail!("Unexpected successful registry of signum {:?}", User1);
|
|
||||||
}
|
|
||||||
Err(..) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue