mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-08 00:00:13 +02:00
signal: Change constructors to return a result instead of lazy future (#1340)
This commit is contained in:
@@ -2,10 +2,8 @@
|
||||
use crate::unix::Signal as Inner;
|
||||
#[cfg(windows)]
|
||||
use crate::windows::Event as Inner;
|
||||
use crate::IoFuture;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_util::future::FutureExt;
|
||||
use futures_util::try_future::TryFutureExt;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use tokio_reactor::Handle;
|
||||
@@ -36,7 +34,7 @@ impl CtrlC {
|
||||
/// process.
|
||||
///
|
||||
/// This function binds to the default reactor.
|
||||
pub fn new() -> IoFuture<Self> {
|
||||
pub fn new() -> io::Result<Self> {
|
||||
Self::with_handle(&Handle::default())
|
||||
}
|
||||
|
||||
@@ -44,8 +42,8 @@ impl CtrlC {
|
||||
/// process.
|
||||
///
|
||||
/// This function binds to reactor specified by `handle`.
|
||||
pub fn with_handle(handle: &Handle) -> IoFuture<Self> {
|
||||
Inner::ctrl_c(handle).map_ok(|inner| Self { inner }).boxed()
|
||||
pub fn with_handle(handle: &Handle) -> io::Result<Self> {
|
||||
Inner::ctrl_c(handle).map(|inner| Self { inner })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +51,6 @@ impl Stream for CtrlC {
|
||||
type Item = ();
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
Pin::new(&mut self.inner)
|
||||
.poll_next(cx)
|
||||
.map(|item| item.map(|_| ()))
|
||||
Pin::new(&mut self.inner).poll_next(cx)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-10
@@ -33,7 +33,7 @@
|
||||
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! // Create an infinite stream of "Ctrl+C" notifications. Each item received
|
||||
//! // on this stream may represent multiple ctrl-c signals.
|
||||
//! let ctrl_c = tokio_signal::CtrlC::new().await?;
|
||||
//! let ctrl_c = tokio_signal::CtrlC::new()?;
|
||||
//!
|
||||
//! // Process each ctrl-c as it comes in
|
||||
//! let prog = ctrl_c.for_each(|_| {
|
||||
@@ -60,7 +60,7 @@
|
||||
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! // Create an infinite stream of "Ctrl+C" notifications. Each item received
|
||||
//! // on this stream may represent multiple ctrl-c signals.
|
||||
//! let ctrl_c = tokio_signal::CtrlC::new().await?;
|
||||
//! let ctrl_c = tokio_signal::CtrlC::new()?;
|
||||
//!
|
||||
//! // Process each ctrl-c as it comes in
|
||||
//! let prog = ctrl_c.for_each(|_| {
|
||||
@@ -72,7 +72,7 @@
|
||||
//!
|
||||
//! // Like the previous example, this is an infinite stream of signals
|
||||
//! // being received, and signals may be coalesced while pending.
|
||||
//! let stream = Signal::new(SIGHUP).await?;
|
||||
//! let stream = Signal::new(SIGHUP)?;
|
||||
//!
|
||||
//! // Convert out stream into a future and block the program
|
||||
//! let (signal, _signal) = stream.into_future().await;
|
||||
@@ -84,10 +84,6 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use futures_core::future::Future;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
mod ctrl_c;
|
||||
mod registry;
|
||||
|
||||
@@ -101,7 +97,4 @@ mod os {
|
||||
pub mod unix;
|
||||
pub mod windows;
|
||||
|
||||
/// A future whose output is `io::Result<T>`
|
||||
pub type IoFuture<T> = Pin<Box<dyn Future<Output = io::Result<T>> + Send>>;
|
||||
|
||||
pub use ctrl_c::CtrlC;
|
||||
|
||||
+14
-22
@@ -12,9 +12,7 @@ use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Once;
|
||||
|
||||
use crate::IoFuture;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_util::future::{self, FutureExt};
|
||||
use libc::c_int;
|
||||
use mio_uds::UnixStream;
|
||||
use std::future::Future;
|
||||
@@ -283,7 +281,7 @@ impl Signal {
|
||||
/// * If the previous initialization of this specific signal failed.
|
||||
/// * If the signal is one of
|
||||
/// [`signal_hook::FORBIDDEN`](https://docs.rs/signal-hook/*/signal_hook/fn.register.html#panics)
|
||||
pub fn new(signal: c_int) -> IoFuture<Signal> {
|
||||
pub fn new(signal: c_int) -> io::Result<Self> {
|
||||
Signal::with_handle(signal, &Handle::default())
|
||||
}
|
||||
|
||||
@@ -305,27 +303,23 @@ impl Signal {
|
||||
/// 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 with_handle(signal: c_int, handle: &Handle) -> IoFuture<Signal> {
|
||||
let handle = handle.clone();
|
||||
future::lazy(move |_| {
|
||||
// Turn the signal delivery on once we are ready for it
|
||||
signal_enable(signal)?;
|
||||
pub fn with_handle(signal: c_int, handle: &Handle) -> io::Result<Self> {
|
||||
// Turn the signal delivery on once we are ready for it
|
||||
signal_enable(signal)?;
|
||||
|
||||
// Ensure there's a driver for our associated event loop processing
|
||||
// signals.
|
||||
let driver = Driver::new(&handle)?;
|
||||
// Ensure there's a driver for our associated event loop processing
|
||||
// signals.
|
||||
let driver = Driver::new(&handle)?;
|
||||
|
||||
// One wakeup in a queue is enough, no need for us to buffer up any
|
||||
// more.
|
||||
let (tx, rx) = channel(1);
|
||||
globals().register_listener(signal as EventId, tx);
|
||||
// One wakeup in a queue is enough, no need for us to buffer up any
|
||||
// more.
|
||||
let (tx, rx) = channel(1);
|
||||
globals().register_listener(signal as EventId, tx);
|
||||
|
||||
Ok(Signal { driver, rx })
|
||||
})
|
||||
.boxed()
|
||||
Ok(Signal { driver, rx })
|
||||
}
|
||||
|
||||
pub(crate) fn ctrl_c(handle: &Handle) -> IoFuture<Signal> {
|
||||
pub(crate) fn ctrl_c(handle: &Handle) -> io::Result<Self> {
|
||||
Self::with_handle(libc::SIGINT, handle)
|
||||
}
|
||||
}
|
||||
@@ -365,9 +359,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn ctrl_c() {
|
||||
let ctrl_c = with_timeout(crate::CtrlC::new())
|
||||
.await
|
||||
.expect("failed to init ctrl_c");
|
||||
let ctrl_c = crate::CtrlC::new().expect("failed to init ctrl_c");
|
||||
|
||||
let (fire, wait) = oneshot::channel();
|
||||
|
||||
|
||||
+27
-37
@@ -15,8 +15,6 @@ use std::sync::Once;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures_core::stream::Stream;
|
||||
use futures_util::future::{self, FutureExt};
|
||||
use futures_util::try_future::TryFutureExt;
|
||||
use tokio_reactor::Handle;
|
||||
use tokio_sync::mpsc::{channel, Receiver, Sender};
|
||||
use winapi::shared::minwindef::*;
|
||||
@@ -24,7 +22,6 @@ use winapi::um::consoleapi::SetConsoleCtrlHandler;
|
||||
use winapi::um::wincon::*;
|
||||
|
||||
use crate::registry::{globals, EventId, EventInfo, Init, Storage};
|
||||
use crate::IoFuture;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct OsStorage {
|
||||
@@ -74,8 +71,6 @@ impl Init for OsExtraData {
|
||||
}
|
||||
}
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
/// Stream of events discovered via `SetConsoleCtrlHandler`.
|
||||
///
|
||||
/// This structure can be used to listen for events of the type `CTRL_C_EVENT`
|
||||
@@ -106,7 +101,7 @@ impl Event {
|
||||
///
|
||||
/// This function will register a handler via `SetConsoleCtrlHandler` and
|
||||
/// deliver notifications to the returned stream.
|
||||
pub(crate) fn ctrl_c(handle: &Handle) -> IoFuture<Event> {
|
||||
pub(crate) fn ctrl_c(handle: &Handle) -> io::Result<Self> {
|
||||
Event::new(CTRL_C_EVENT, handle)
|
||||
}
|
||||
|
||||
@@ -114,27 +109,17 @@ impl Event {
|
||||
///
|
||||
/// This function will register a handler via `SetConsoleCtrlHandler` and
|
||||
/// deliver notifications to the returned stream.
|
||||
fn ctrl_break_handle(handle: &Handle) -> IoFuture<Event> {
|
||||
fn ctrl_break_handle(handle: &Handle) -> io::Result<Self> {
|
||||
Event::new(CTRL_BREAK_EVENT, handle)
|
||||
}
|
||||
|
||||
fn new(signum: DWORD, _handle: &Handle) -> IoFuture<Event> {
|
||||
future::lazy(move |_| {
|
||||
let mut init = None;
|
||||
INIT.call_once(|| {
|
||||
init = Some(global_init());
|
||||
});
|
||||
fn new(signum: DWORD, _handle: &Handle) -> io::Result<Self> {
|
||||
global_init()?;
|
||||
|
||||
if let Some(Err(e)) = init {
|
||||
return Err(e);
|
||||
}
|
||||
let (tx, rx) = channel(1);
|
||||
globals().register_listener(signum as EventId, tx);
|
||||
|
||||
let (tx, rx) = channel(1);
|
||||
globals().register_listener(signum as EventId, tx);
|
||||
|
||||
Ok(Event { rx })
|
||||
})
|
||||
.boxed()
|
||||
Ok(Event { rx })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,14 +132,21 @@ impl Stream for Event {
|
||||
}
|
||||
|
||||
fn global_init() -> io::Result<()> {
|
||||
unsafe {
|
||||
let rc = SetConsoleCtrlHandler(Some(handler), TRUE);
|
||||
if rc == 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
let mut init = None;
|
||||
INIT.call_once(|| unsafe {
|
||||
let rc = SetConsoleCtrlHandler(Some(handler), TRUE);
|
||||
let ret = if rc == 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
init = Some(ret);
|
||||
});
|
||||
|
||||
init.unwrap_or_else(|| Ok(()))
|
||||
}
|
||||
|
||||
impl Future for DriverTask {
|
||||
@@ -210,7 +202,7 @@ impl CtrlBreak {
|
||||
/// process.
|
||||
///
|
||||
/// This function binds to the default reactor.
|
||||
pub fn new() -> IoFuture<Self> {
|
||||
pub fn new() -> io::Result<Self> {
|
||||
Self::with_handle(&Handle::default())
|
||||
}
|
||||
|
||||
@@ -218,10 +210,8 @@ impl CtrlBreak {
|
||||
/// process.
|
||||
///
|
||||
/// This function binds to reactor specified by `handle`.
|
||||
pub fn with_handle(handle: &Handle) -> IoFuture<Self> {
|
||||
Event::ctrl_break_handle(handle)
|
||||
.map_ok(|inner| Self { inner })
|
||||
.boxed()
|
||||
pub fn with_handle(handle: &Handle) -> io::Result<Self> {
|
||||
Event::ctrl_break_handle(handle).map(|inner| Self { inner })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +228,7 @@ impl Stream for CtrlBreak {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures_util::future::FutureExt;
|
||||
use futures_util::future::{self, FutureExt};
|
||||
use futures_util::stream::StreamExt;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::current_thread;
|
||||
@@ -254,7 +244,7 @@ mod tests {
|
||||
// first event loop cannot go away
|
||||
let mut rt = current_thread::Runtime::new().unwrap();
|
||||
let event_ctrl_c = rt
|
||||
.block_on(with_timeout(crate::CtrlC::new()))
|
||||
.block_on(with_timeout(future::lazy(|_| crate::CtrlC::new())))
|
||||
.expect("failed to run future");
|
||||
|
||||
// Windows doesn't have a good programmatic way of sending events
|
||||
@@ -267,7 +257,7 @@ mod tests {
|
||||
let _ = rt.block_on(with_timeout(event_ctrl_c.into_future()));
|
||||
|
||||
let event_ctrl_break = rt
|
||||
.block_on(with_timeout(CtrlBreak::new()))
|
||||
.block_on(with_timeout(future::lazy(|_| CtrlBreak::new())))
|
||||
.expect("failed to run future");
|
||||
|
||||
unsafe {
|
||||
|
||||
Reference in New Issue
Block a user