mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-28 12:10:37 +00:00
signal: Provide the new kind of Signal stream
Which is just a wrapper around the futures::sync::mpsc. The sender is in a global registry. The part that connects the wakeups to the senders in the registry doesn't yet exist.
This commit is contained in:
parent
ed4359bb26
commit
04d949c380
123
src/unix.rs
123
src/unix.rs
@ -10,16 +10,24 @@ extern crate mio;
|
|||||||
extern crate tokio_uds;
|
extern crate tokio_uds;
|
||||||
extern crate nix;
|
extern crate nix;
|
||||||
|
|
||||||
use std::sync::{Once, ONCE_INIT};
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
use self::libc::c_int;
|
use self::libc::c_int;
|
||||||
use self::nix::unistd::pipe;
|
use self::nix::unistd::pipe;
|
||||||
use self::nix::sys::signal::{SigAction, SigHandler, SigSet, SA_NOCLDSTOP, SA_RESTART, sigaction};
|
use self::nix::sys::signal::{SigAction, SigHandler, SigSet, SA_NOCLDSTOP, SA_RESTART, sigaction};
|
||||||
use self::nix::sys::signal::Signal as NixSignal;
|
use self::nix::sys::signal::Signal as NixSignal;
|
||||||
use self::nix::sys::socket::{send, MSG_DONTWAIT};
|
use self::nix::sys::socket::{send, MSG_DONTWAIT};
|
||||||
|
use futures::{Future, IntoFuture};
|
||||||
|
use futures::sync::mpsc::{Receiver, Sender, channel};
|
||||||
|
use futures::{Stream, Poll};
|
||||||
|
use tokio_core::reactor::Handle;
|
||||||
|
use tokio_core::io::IoFuture;
|
||||||
|
|
||||||
|
pub use self::libc::{SIGINT, SIGTERM, SIGUSR1, SIGUSR2};
|
||||||
|
pub use self::libc::{SIGHUP, SIGQUIT, SIGPIPE, SIGALRM, SIGTRAP};
|
||||||
|
|
||||||
// Number of different unix signals
|
// Number of different unix signals
|
||||||
const SIGNUM: usize = 32;
|
const SIGNUM: usize = 32;
|
||||||
@ -27,6 +35,8 @@ const SIGNUM: usize = 32;
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct SignalInfo {
|
struct SignalInfo {
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
|
// The ones interested in this signal
|
||||||
|
recipients: Vec<Sender<c_int>>,
|
||||||
// TODO: Other stuff, like the previous sigaction to call
|
// TODO: Other stuff, like the previous sigaction to call
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,22 +91,7 @@ fn signal_enable(signal: c_int) -> RawFd {
|
|||||||
globals.receiver
|
globals.receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::cell::RefCell;
|
// TODO: Go through the docs, they are a copy-paste from the previous version
|
||||||
use std::io::{self, Write, Read};
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use futures::future;
|
|
||||||
use futures::stream::Fuse;
|
|
||||||
use futures::sync::mpsc;
|
|
||||||
use futures::sync::oneshot;
|
|
||||||
use futures::{Future, Stream, IntoFuture, Poll, Async};
|
|
||||||
use self::tokio_uds::UnixStream;
|
|
||||||
use tokio_core::io::IoFuture;
|
|
||||||
use tokio_core::reactor::{PollEvented, Handle};
|
|
||||||
|
|
||||||
static INIT: Once = ONCE_INIT;
|
|
||||||
static mut GLOBAL_STATE: *mut GlobalState = 0 as *mut _;
|
|
||||||
|
|
||||||
/// An implementation of `Stream` for receiving a particular type of signal.
|
/// An implementation of `Stream` for receiving a particular type of signal.
|
||||||
///
|
///
|
||||||
/// This structure implements the `Stream` trait and represents notifications
|
/// This structure implements the `Stream` trait and represents notifications
|
||||||
@ -134,6 +129,74 @@ static mut GLOBAL_STATE: *mut GlobalState = 0 as *mut _;
|
|||||||
/// If you've got any questions about this feel free to open an issue on the
|
/// If you've got any questions about this feel free to open an issue on the
|
||||||
/// repo, though, as I'd love to chat about this! In other words, I'd love to
|
/// repo, though, as I'd love to chat about this! In other words, I'd love to
|
||||||
/// alleviate some of these limitations if possible!
|
/// alleviate some of these limitations if possible!
|
||||||
|
pub struct Signal(Receiver<c_int>);
|
||||||
|
|
||||||
|
impl Signal {
|
||||||
|
// TODO: Revisit the docs, they are from the previous version
|
||||||
|
/// Creates a new stream which will receive notifications when the current
|
||||||
|
/// process receives the signal `signum`.
|
||||||
|
///
|
||||||
|
/// This function will create a new stream which may be based on the
|
||||||
|
/// event loop handle provided. This function returns a future which will
|
||||||
|
/// then resolve to the signal stream, if successful.
|
||||||
|
///
|
||||||
|
/// The `Signal` stream is an infinite stream which will receive
|
||||||
|
/// notifications whenever a signal is received. More documentation can be
|
||||||
|
/// found on `Signal` itself, but to reiterate:
|
||||||
|
///
|
||||||
|
/// * Signals may be coalesced beyond what the kernel already does.
|
||||||
|
/// * While multiple event loops are supported, the first event loop to
|
||||||
|
/// register a signal handler must be active to deliver signal
|
||||||
|
/// notifications
|
||||||
|
/// * Once a signal handle is registered with the process the underlying
|
||||||
|
/// libc signal handler is never unregistered.
|
||||||
|
///
|
||||||
|
/// A `Signal` stream can be created for a particular signal number
|
||||||
|
/// multiple times. When a signal is received then all the associated
|
||||||
|
/// channels will receive the signal notification.
|
||||||
|
pub fn new(signal: c_int, handle: &Handle) -> IoFuture<Signal> {
|
||||||
|
let index = signal as usize;
|
||||||
|
// One wakeup in a queue is enough
|
||||||
|
let (sender, receiver) = channel(1);
|
||||||
|
{ // Hold the mutex only a short while
|
||||||
|
let mut siginfo = globals.signals[index].lock().unwrap();
|
||||||
|
siginfo.recipients.push(sender);
|
||||||
|
}
|
||||||
|
// Turn the signal delivery on once we are ready for it
|
||||||
|
let wakeup = signal_enable(signal);
|
||||||
|
// TODO: Init the driving task for this handle
|
||||||
|
Ok(Signal(receiver)).into_future().boxed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stream for Signal {
|
||||||
|
type Item = c_int;
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Option<c_int>, io::Error> {
|
||||||
|
// It seems the channel doesn't generate any errors anyway
|
||||||
|
self.0.poll().map_err(|_| io::Error::new(io::ErrorKind::Other, "Unknown futures::sync::mpsc error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Drop for Signal and remove the other end proactively?
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::io::{self, Write, Read};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use futures::future;
|
||||||
|
use futures::stream::Fuse;
|
||||||
|
use futures::sync::mpsc;
|
||||||
|
use futures::sync::oneshot;
|
||||||
|
use self::tokio_uds::UnixStream;
|
||||||
|
use tokio_core::reactor::{PollEvented, Handle};
|
||||||
|
|
||||||
|
static INIT: Once = ONCE_INIT;
|
||||||
|
static mut GLOBAL_STATE: *mut GlobalState = 0 as *mut _;
|
||||||
|
|
||||||
pub struct Signal {
|
pub struct Signal {
|
||||||
signum: c_int,
|
signum: c_int,
|
||||||
reg: PollEvented<MyRegistration>,
|
reg: PollEvented<MyRegistration>,
|
||||||
@ -167,31 +230,7 @@ struct SignalState {
|
|||||||
tasks: Vec<(RefCell<oneshot::Receiver<()>>, mio::SetReadiness)>,
|
tasks: Vec<(RefCell<oneshot::Receiver<()>>, mio::SetReadiness)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::libc::{SIGINT, SIGTERM, SIGUSR1, SIGUSR2};
|
|
||||||
pub use self::libc::{SIGHUP, SIGQUIT, SIGPIPE, SIGALRM, SIGTRAP};
|
|
||||||
|
|
||||||
impl Signal {
|
impl Signal {
|
||||||
/// Creates a new stream which will receive notifications when the current
|
|
||||||
/// process receives the signal `signum`.
|
|
||||||
///
|
|
||||||
/// This function will create a new stream which may be based on the
|
|
||||||
/// event loop handle provided. This function returns a future which will
|
|
||||||
/// then resolve to the signal stream, if successful.
|
|
||||||
///
|
|
||||||
/// The `Signal` stream is an infinite stream which will receive
|
|
||||||
/// notifications whenever a signal is received. More documentation can be
|
|
||||||
/// found on `Signal` itself, but to reiterate:
|
|
||||||
///
|
|
||||||
/// * Signals may be coalesced beyond what the kernel already does.
|
|
||||||
/// * While multiple event loops are supported, the first event loop to
|
|
||||||
/// register a signal handler must be active to deliver signal
|
|
||||||
/// notifications
|
|
||||||
/// * Once a signal handle is registered with the process the underlying
|
|
||||||
/// libc signal handler is never unregistered.
|
|
||||||
///
|
|
||||||
/// A `Signal` stream can be created for a particular signal number
|
|
||||||
/// multiple times. When a signal is received then all the associated
|
|
||||||
/// channels will receive the signal notification.
|
|
||||||
pub fn new(signum: c_int, handle: &Handle) -> IoFuture<Signal> {
|
pub fn new(signum: c_int, handle: &Handle) -> IoFuture<Signal> {
|
||||||
let mut init = None;
|
let mut init = None;
|
||||||
INIT.call_once(|| {
|
INIT.call_once(|| {
|
||||||
@ -464,3 +503,5 @@ impl mio::Evented for MyRegistration {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user