summaryrefslogtreecommitdiffstats
path: root/vendor/tokio/src/signal
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/tokio/src/signal
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tokio/src/signal')
-rw-r--r--vendor/tokio/src/signal/ctrl_c.rs9
-rw-r--r--vendor/tokio/src/signal/mod.rs4
-rw-r--r--vendor/tokio/src/signal/registry.rs43
-rw-r--r--vendor/tokio/src/signal/reusable_box.rs12
-rw-r--r--vendor/tokio/src/signal/unix.rs116
-rw-r--r--vendor/tokio/src/signal/unix/driver.rs207
-rw-r--r--vendor/tokio/src/signal/windows.rs525
-rw-r--r--vendor/tokio/src/signal/windows/stub.rs25
-rw-r--r--vendor/tokio/src/signal/windows/sys.rs229
9 files changed, 719 insertions, 451 deletions
diff --git a/vendor/tokio/src/signal/ctrl_c.rs b/vendor/tokio/src/signal/ctrl_c.rs
index 1eeeb85aa..b26ab7ead 100644
--- a/vendor/tokio/src/signal/ctrl_c.rs
+++ b/vendor/tokio/src/signal/ctrl_c.rs
@@ -47,6 +47,15 @@ use std::io;
/// println!("received ctrl-c event");
/// }
/// ```
+///
+/// Listen in the background:
+///
+/// ```rust,no_run
+/// tokio::spawn(async move {
+/// tokio::signal::ctrl_c().await.unwrap();
+/// // Your handler here
+/// });
+/// ```
pub async fn ctrl_c() -> io::Result<()> {
os_impl::ctrl_c()?.recv().await;
Ok(())
diff --git a/vendor/tokio/src/signal/mod.rs b/vendor/tokio/src/signal/mod.rs
index fe572f041..3aacc60ef 100644
--- a/vendor/tokio/src/signal/mod.rs
+++ b/vendor/tokio/src/signal/mod.rs
@@ -1,4 +1,4 @@
-//! Asynchronous signal handling for Tokio
+//! Asynchronous signal handling for Tokio.
//!
//! Note that signal handling is in general a very tricky topic and should be
//! used with great care. This crate attempts to implement 'best practice' for
@@ -48,7 +48,7 @@ use std::task::{Context, Poll};
mod ctrl_c;
pub use ctrl_c::ctrl_c;
-mod registry;
+pub(crate) mod registry;
mod os {
#[cfg(unix)]
diff --git a/vendor/tokio/src/signal/registry.rs b/vendor/tokio/src/signal/registry.rs
index 8b89108a6..48e98c832 100644
--- a/vendor/tokio/src/signal/registry.rs
+++ b/vendor/tokio/src/signal/registry.rs
@@ -1,12 +1,10 @@
#![allow(clippy::unit_arg)]
use crate::signal::os::{OsExtraData, OsStorage};
-
use crate::sync::watch;
+use crate::util::once_cell::OnceCell;
-use once_cell::sync::Lazy;
use std::ops;
-use std::pin::Pin;
use std::sync::atomic::{AtomicBool, Ordering};
pub(crate) type EventId = usize;
@@ -152,19 +150,25 @@ impl Globals {
}
}
-pub(crate) fn globals() -> Pin<&'static Globals>
+fn globals_init() -> Globals
where
OsExtraData: 'static + Send + Sync + Init,
OsStorage: 'static + Send + Sync + Init,
{
- static GLOBALS: Lazy<Pin<Box<Globals>>> = Lazy::new(|| {
- Box::pin(Globals {
- extra: OsExtraData::init(),
- registry: Registry::new(OsStorage::init()),
- })
- });
-
- GLOBALS.as_ref()
+ Globals {
+ extra: OsExtraData::init(),
+ registry: Registry::new(OsStorage::init()),
+ }
+}
+
+pub(crate) fn globals() -> &'static Globals
+where
+ OsExtraData: 'static + Send + Sync + Init,
+ OsStorage: 'static + Send + Sync + Init,
+{
+ static GLOBALS: OnceCell<Globals> = OnceCell::new();
+
+ GLOBALS.get(globals_init)
}
#[cfg(all(test, not(loom)))]
@@ -202,7 +206,12 @@ mod tests {
registry.broadcast();
// Yield so the previous broadcast can get received
- crate::time::sleep(std::time::Duration::from_millis(10)).await;
+ //
+ // This yields many times since the block_on task is only polled every 61
+ // ticks.
+ for _ in 0..100 {
+ crate::task::yield_now().await;
+ }
// Send subsequent signal
registry.record_event(0);
@@ -232,7 +241,7 @@ mod tests {
#[test]
fn record_invalid_event_does_nothing() {
let registry = Registry::new(vec![EventInfo::default()]);
- registry.record_event(42);
+ registry.record_event(1302);
}
#[test]
@@ -240,17 +249,17 @@ mod tests {
let registry = Registry::new(vec![EventInfo::default(), EventInfo::default()]);
registry.record_event(0);
- assert_eq!(false, registry.broadcast());
+ assert!(!registry.broadcast());
let first = registry.register_listener(0);
let second = registry.register_listener(1);
registry.record_event(0);
- assert_eq!(true, registry.broadcast());
+ assert!(registry.broadcast());
drop(first);
registry.record_event(0);
- assert_eq!(false, registry.broadcast());
+ assert!(!registry.broadcast());
drop(second);
}
diff --git a/vendor/tokio/src/signal/reusable_box.rs b/vendor/tokio/src/signal/reusable_box.rs
index 426ecb06f..796fa210b 100644
--- a/vendor/tokio/src/signal/reusable_box.rs
+++ b/vendor/tokio/src/signal/reusable_box.rs
@@ -30,7 +30,7 @@ impl<T> ReusableBoxFuture<T> {
Self { boxed }
}
- /// Replace the future currently stored in this box.
+ /// Replaces the future currently stored in this box.
///
/// This reallocates if and only if the layout of the provided future is
/// different from the layout of the currently stored future.
@@ -43,7 +43,7 @@ impl<T> ReusableBoxFuture<T> {
}
}
- /// Replace the future currently stored in this box.
+ /// Replaces the future currently stored in this box.
///
/// This function never reallocates, but returns an error if the provided
/// future has a different size or alignment from the currently stored
@@ -70,7 +70,7 @@ impl<T> ReusableBoxFuture<T> {
}
}
- /// Set the current future.
+ /// Sets the current future.
///
/// # Safety
///
@@ -103,14 +103,14 @@ impl<T> ReusableBoxFuture<T> {
}
}
- /// Get a pinned reference to the underlying future.
+ /// Gets a pinned reference to the underlying future.
pub(crate) fn get_pin(&mut self) -> Pin<&mut (dyn Future<Output = T> + Send)> {
// SAFETY: The user of this box cannot move the box, and we do not move it
// either.
unsafe { Pin::new_unchecked(self.boxed.as_mut()) }
}
- /// Poll the future stored inside this box.
+ /// Polls the future stored inside this box.
pub(crate) fn poll(&mut self, cx: &mut Context<'_>) -> Poll<T> {
self.get_pin().poll(cx)
}
@@ -119,7 +119,7 @@ impl<T> ReusableBoxFuture<T> {
impl<T> Future for ReusableBoxFuture<T> {
type Output = T;
- /// Poll the future stored inside this box.
+ /// Polls the future stored inside this box.
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
Pin::into_inner(self).get_pin().poll(cx)
}
diff --git a/vendor/tokio/src/signal/unix.rs b/vendor/tokio/src/signal/unix.rs
index f96b2f4c2..ae5c13085 100644
--- a/vendor/tokio/src/signal/unix.rs
+++ b/vendor/tokio/src/signal/unix.rs
@@ -4,30 +4,33 @@
//! `Signal` type for receiving notifications of signals.
#![cfg(unix)]
+#![cfg_attr(docsrs, doc(cfg(all(unix, feature = "signal"))))]
+use crate::runtime::scheduler;
+use crate::runtime::signal::Handle;
use crate::signal::registry::{globals, EventId, EventInfo, Globals, Init, Storage};
use crate::signal::RxFuture;
use crate::sync::watch;
use mio::net::UnixStream;
use std::io::{self, Error, ErrorKind, Write};
-use std::pin::Pin;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
use std::task::{Context, Poll};
-pub(crate) mod driver;
-use self::driver::Handle;
-
pub(crate) type OsStorage = Vec<SignalInfo>;
-// Number of different unix signals
-// (FreeBSD has 33)
-const SIGNUM: usize = 33;
-
impl Init for OsStorage {
fn init() -> Self {
- (0..SIGNUM).map(|_| SignalInfo::default()).collect()
+ // There are reliable signals ranging from 1 to 33 available on every Unix platform.
+ #[cfg(not(target_os = "linux"))]
+ let possible = 0..=33;
+
+ // On Linux, there are additional real-time signals available.
+ #[cfg(target_os = "linux")]
+ let possible = 0..=libc::SIGRTMAX();
+
+ possible.map(|_| SignalInfo::default()).collect()
}
}
@@ -47,7 +50,7 @@ impl Storage for OsStorage {
#[derive(Debug)]
pub(crate) struct OsExtraData {
sender: UnixStream,
- receiver: UnixStream,
+ pub(crate) receiver: UnixStream,
}
impl Init for OsExtraData {
@@ -59,7 +62,7 @@ impl Init for OsExtraData {
}
/// Represents the specific kind of signal to listen for.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct SignalKind(libc::c_int);
impl SignalKind {
@@ -79,15 +82,26 @@ impl SignalKind {
// unlikely to change to other types, but technically libc can change this
// in the future minor version.
// See https://github.com/tokio-rs/tokio/issues/3767 for more.
- pub fn from_raw(signum: std::os::raw::c_int) -> Self {
+ pub const fn from_raw(signum: std::os::raw::c_int) -> Self {
Self(signum as libc::c_int)
}
+ /// Get the signal's numeric value.
+ ///
+ /// ```rust
+ /// # use tokio::signal::unix::SignalKind;
+ /// let kind = SignalKind::interrupt();
+ /// assert_eq!(kind.as_raw_value(), libc::SIGINT);
+ /// ```
+ pub const fn as_raw_value(&self) -> std::os::raw::c_int {
+ self.0
+ }
+
/// Represents the SIGALRM signal.
///
/// On Unix systems this signal is sent when a real-time timer has expired.
/// By default, the process is terminated by this signal.
- pub fn alarm() -> Self {
+ pub const fn alarm() -> Self {
Self(libc::SIGALRM)
}
@@ -95,7 +109,7 @@ impl SignalKind {
///
/// On Unix systems this signal is sent when the status of a child process
/// has changed. By default, this signal is ignored.
- pub fn child() -> Self {
+ pub const fn child() -> Self {
Self(libc::SIGCHLD)
}
@@ -103,7 +117,7 @@ impl SignalKind {
///
/// On Unix systems this signal is sent when the terminal is disconnected.
/// By default, the process is terminated by this signal.
- pub fn hangup() -> Self {
+ pub const fn hangup() -> Self {
Self(libc::SIGHUP)
}
@@ -118,7 +132,7 @@ impl SignalKind {
target_os = "netbsd",
target_os = "openbsd"
))]
- pub fn info() -> Self {
+ pub const fn info() -> Self {
Self(libc::SIGINFO)
}
@@ -126,7 +140,7 @@ impl SignalKind {
///
/// On Unix systems this signal is sent to interrupt a program.
/// By default, the process is terminated by this signal.
- pub fn interrupt() -> Self {
+ pub const fn interrupt() -> Self {
Self(libc::SIGINT)
}
@@ -134,7 +148,7 @@ impl SignalKind {
///
/// On Unix systems this signal is sent when I/O operations are possible
/// on some file descriptor. By default, this signal is ignored.
- pub fn io() -> Self {
+ pub const fn io() -> Self {
Self(libc::SIGIO)
}
@@ -143,7 +157,7 @@ impl SignalKind {
/// On Unix systems this signal is sent when the process attempts to write
/// to a pipe which has no reader. By default, the process is terminated by
/// this signal.
- pub fn pipe() -> Self {
+ pub const fn pipe() -> Self {
Self(libc::SIGPIPE)
}
@@ -152,7 +166,7 @@ impl SignalKind {
/// On Unix systems this signal is sent to issue a shutdown of the
/// process, after which the OS will dump the process core.
/// By default, the process is terminated by this signal.
- pub fn quit() -> Self {
+ pub const fn quit() -> Self {
Self(libc::SIGQUIT)
}
@@ -160,7 +174,7 @@ impl SignalKind {
///
/// On Unix systems this signal is sent to issue a shutdown of the
/// process. By default, the process is terminated by this signal.
- pub fn terminate() -> Self {
+ pub const fn terminate() -> Self {
Self(libc::SIGTERM)
}
@@ -168,7 +182,7 @@ impl SignalKind {
///
/// On Unix systems this is a user defined signal.
/// By default, the process is terminated by this signal.
- pub fn user_defined1() -> Self {
+ pub const fn user_defined1() -> Self {
Self(libc::SIGUSR1)
}
@@ -176,7 +190,7 @@ impl SignalKind {
///
/// On Unix systems this is a user defined signal.
/// By default, the process is terminated by this signal.
- pub fn user_defined2() -> Self {
+ pub const fn user_defined2() -> Self {
Self(libc::SIGUSR2)
}
@@ -184,11 +198,23 @@ impl SignalKind {
///
/// On Unix systems this signal is sent when the terminal window is resized.
/// By default, this signal is ignored.
- pub fn window_change() -> Self {
+ pub const fn window_change() -> Self {
Self(libc::SIGWINCH)
}
}
+impl From<std::os::raw::c_int> for SignalKind {
+ fn from(signum: std::os::raw::c_int) -> Self {
+ Self::from_raw(signum as libc::c_int)
+ }
+}
+
+impl From<SignalKind> for std::os::raw::c_int {
+ fn from(kind: SignalKind) -> Self {
+ kind.as_raw_value()
+ }
+}
+
pub(crate) struct SignalInfo {
event_info: EventInfo,
init: Once,
@@ -213,7 +239,7 @@ impl Default for SignalInfo {
/// 2. Wake up the driver by writing a byte to a pipe
///
/// Those two operations should both be async-signal safe.
-fn action(globals: Pin<&'static Globals>, signal: libc::c_int) {
+fn action(globals: &'static Globals, signal: libc::c_int) {
globals.record_event(signal as EventId);
// Send a wakeup, ignore any errors (anything reasonably possible is
@@ -266,7 +292,11 @@ fn signal_enable(signal: SignalKind, handle: &Handle) -> io::Result<()> {
}
}
-/// A stream of events for receiving a particular type of OS signal.
+/// An listener for receiving a particular type of OS signal.
+///
+/// The listener can be turned into a `Stream` using [`SignalStream`].
+///
+/// [`SignalStream`]: https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/struct.SignalStream.html
///
/// In general signal handling on Unix is a pretty tricky topic, and this
/// structure is no exception! There are some important limitations to keep in
@@ -281,7 +311,7 @@ fn signal_enable(signal: SignalKind, handle: &Handle) -> io::Result<()> {
/// Once `poll` has been called, however, a further signal is guaranteed to
/// be yielded as an item.
///
-/// Put another way, any element pulled off the returned stream corresponds to
+/// Put another way, any element pulled off the returned listener corresponds to
/// *at least one* signal, but possibly more.
///
/// * Signal handling in general is relatively inefficient. Although some
@@ -319,11 +349,11 @@ fn signal_enable(signal: SignalKind, handle: &Handle) -> io::Result<()> {
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// // An infinite stream of hangup signals.
-/// let mut stream = signal(SignalKind::hangup())?;
+/// let mut sig = signal(SignalKind::hangup())?;
///
/// // Print whenever a HUP signal is received
/// loop {
-/// stream.recv().await;
+/// sig.recv().await;
/// println!("got signal HUP");
/// }
/// }
@@ -334,7 +364,7 @@ pub struct Signal {
inner: RxFuture,
}
-/// Creates a new stream which will receive notifications when the current
+/// Creates a new listener which will receive notifications when the current
/// process receives the specified signal `kind`.
///
/// This function will create a new stream which binds to the default reactor.
@@ -356,8 +386,15 @@ pub struct Signal {
/// * If the previous initialization of this specific signal failed.
/// * If the signal is one of
/// [`signal_hook::FORBIDDEN`](fn@signal_hook_registry::register#panics)
+///
+/// # Panics
+///
+/// This function panics if there is no current reactor set, or if the `rt`
+/// feature flag is not enabled.
+#[track_caller]
pub fn signal(kind: SignalKind) -> io::Result<Signal> {
- let rx = signal_with_handle(kind, &Handle::current())?;
+ let handle = scheduler::Handle::current();
+ let rx = signal_with_handle(kind, handle.driver().signal())?;
Ok(Signal {
inner: RxFuture::new(rx),
@@ -379,6 +416,12 @@ impl Signal {
///
/// `None` is returned if no more events can be received by this stream.
///
+ /// # Cancel safety
+ ///
+ /// This method is cancel safe. If you use it as the event in a
+ /// [`tokio::select!`](crate::select) statement and some other branch
+ /// completes first, then it is guaranteed that no signal is lost.
+ ///
/// # Examples
///
/// Wait for SIGHUP
@@ -473,4 +516,15 @@ mod tests {
)
.unwrap_err();
}
+
+ #[test]
+ fn from_c_int() {
+ assert_eq!(SignalKind::from(2), SignalKind::interrupt());
+ }
+
+ #[test]
+ fn into_c_int() {
+ let value: std::os::raw::c_int = SignalKind::interrupt().into();
+ assert_eq!(value, libc::SIGINT as _);
+ }
}
diff --git a/vendor/tokio/src/signal/unix/driver.rs b/vendor/tokio/src/signal/unix/driver.rs
deleted file mode 100644
index 5fe7c354c..000000000
--- a/vendor/tokio/src/signal/unix/driver.rs
+++ /dev/null
@@ -1,207 +0,0 @@
-#![cfg_attr(not(feature = "rt"), allow(dead_code))]
-
-//! Signal driver
-
-use crate::io::driver::{Driver as IoDriver, Interest};
-use crate::io::PollEvented;
-use crate::park::Park;
-use crate::signal::registry::globals;
-
-use mio::net::UnixStream;
-use std::io::{self, Read};
-use std::ptr;
-use std::sync::{Arc, Weak};
-use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
-use std::time::Duration;
-
-/// Responsible for registering wakeups when an OS signal is received, and
-/// subsequently dispatching notifications to any signal listeners as appropriate.
-///
-/// Note: this driver relies on having an enabled IO driver in order to listen to
-/// pipe write wakeups.
-#[derive(Debug)]
-pub(crate) struct Driver {
- /// Thread parker. The `Driver` park implementation delegates to this.
- park: IoDriver,
-
- /// A pipe for receiving wake events from the signal handler
- receiver: PollEvented<UnixStream>,
-
- /// Shared state
- inner: Arc<Inner>,
-}
-
-#[derive(Clone, Debug, Default)]
-pub(crate) struct Handle {
- inner: Weak<Inner>,
-}
-
-#[derive(Debug)]
-pub(super) struct Inner(());
-
-// ===== impl Driver =====
-
-impl Driver {
- /// Creates a new signal `Driver` instance that delegates wakeups to `park`.
- pub(crate) fn new(park: IoDriver) -> io::Result<Self> {
- use std::mem::ManuallyDrop;
- use std::os::unix::io::{AsRawFd, FromRawFd};
-
- // NB: We give each driver a "fresh" receiver file descriptor to avoid
- // the issues described in alexcrichton/tokio-process#42.
- //
- // In the past we would reuse the actual receiver file descriptor and
- // swallow any errors around double registration of the same descriptor.
- // I'm not sure if the second (failed) registration simply doesn't end
- // up receiving wake up notifications, or there could be some race
- // condition when consuming readiness events, but having distinct
- // descriptors for distinct PollEvented instances appears to mitigate
- // this.
- //
- // Unfortunately we cannot just use a single global PollEvented instance
- // either, since we can't compare Handles or assume they will always
- // point to the exact same reactor.
- //
- // Mio 0.7 removed `try_clone()` as an API due to unexpected behavior
- // with registering dups with the same reactor. In this case, duping is
- // safe as each dup is registered with separate reactors **and** we
- // only expect at least one dup to receive the notification.
-
- // Manually drop as we don't actually own this instance of UnixStream.
- let receiver_fd = globals().receiver.as_raw_fd();
-
- // safety: there is nothing unsafe about this, but the `from_raw_fd` fn is marked as unsafe.
- let original =
- ManuallyDrop::new(unsafe { std::os::unix::net::UnixStream::from_raw_fd(receiver_fd) });
- let receiver = UnixStream::from_std(original.try_clone()?);
- let receiver = PollEvented::new_with_interest_and_handle(
- receiver,
- Interest::READABLE | Interest::WRITABLE,
- park.handle(),
- )?;
-
- Ok(Self {
- park,
- receiver,
- inner: Arc::new(Inner(())),
- })
- }
-
- /// Returns a handle to this event loop which can be sent across threads
- /// and can be used as a proxy to the event loop itself.
- pub(crate) fn handle(&self) -> Handle {
- Handle {
- inner: Arc::downgrade(&self.inner),
- }
- }
-
- fn process(&self) {
- // Check if the pipe is ready to read and therefore has "woken" us up
- //
- // To do so, we will `poll_read_ready` with a noop waker, since we don't
- // need to actually be notified when read ready...
- let waker = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE)) };
- let mut cx = Context::from_waker(&waker);
-
- let ev = match self.receiver.registration().poll_read_ready(&mut cx) {
- Poll::Ready(Ok(ev)) => ev,
- Poll::Ready(Err(e)) => panic!("reactor gone: {}", e),
- Poll::Pending => return, // No wake has arrived, bail
- };
-
- // Drain the pipe completely so we can receive a new readiness event
- // if another signal has come in.
- let mut buf = [0; 128];
- loop {
- match (&*self.receiver).read(&mut buf) {
- Ok(0) => panic!("EOF on self-pipe"),
- Ok(_) => continue, // Keep reading
- Err(e) if e.kind() == io::ErrorKind::WouldBlock => break,
- Err(e) => panic!("Bad read on self-pipe: {}", e),
- }
- }
-
- self.receiver.registration().clear_readiness(ev);
-
- // Broadcast any signals which were received
- globals().broadcast();
- }
-}
-
-const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
-
-unsafe fn noop_clone(_data: *const ()) -> RawWaker {
- RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE)
-}
-
-unsafe fn noop(_data: *const ()) {}
-
-// ===== impl Park for Driver =====
-
-impl Park for Driver {
- type Unpark = <IoDriver as Park>::Unpark;
- type Error = io::Error;
-
- fn unpark(&self) -> Self::Unpark {
- self.park.unpark()
- }
-
- fn park(&mut self) -> Result<(), Self::Error> {
- self.park.park()?;
- self.process();
- Ok(())
- }
-
- fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
- self.park.park_timeout(duration)?;
- self.process();
- Ok(())
- }
-
- fn shutdown(&mut self) {
- self.park.shutdown()
- }
-}
-
-// ===== impl Handle =====
-
-impl Handle {
- pub(super) fn check_inner(&self) -> io::Result<()> {
- if self.inner.strong_count() > 0 {
- Ok(())
- } else {
- Err(io::Error::new(io::ErrorKind::Other, "signal driver gone"))
- }
- }
-}
-
-cfg_rt! {
- impl Handle {
- /// Returns a handle to the current driver
- ///
- /// # Panics
- ///
- /// This function panics if there is no current signal driver set.
- pub(super) fn current() -> Self {
- crate::runtime::context::signal_handle().expect(
- "there is no signal driver running, must be called from the context of Tokio runtime",
- )
- }
- }
-}
-
-cfg_not_rt! {
- impl Handle {
- /// Returns a handle to the current driver
- ///
- /// # Panics
- ///
- /// This function panics if there is no current signal driver set.
- pub(super) fn current() -> Self {
- panic!(
- "there is no signal driver running, must be called from the context of Tokio runtime or with\
- `rt` enabled.",
- )
- }
- }
-}
diff --git a/vendor/tokio/src/signal/windows.rs b/vendor/tokio/src/signal/windows.rs
index c231d6268..2f70f98b1 100644
--- a/vendor/tokio/src/signal/windows.rs
+++ b/vendor/tokio/src/signal/windows.rs
@@ -1,133 +1,28 @@
//! Windows-specific types for signal handling.
//!
-//! This module is only defined on Windows and allows receiving "ctrl-c"
-//! and "ctrl-break" notifications. These events are listened for via the
-//! `SetConsoleCtrlHandler` function which receives events of the type
-//! `CTRL_C_EVENT` and `CTRL_BREAK_EVENT`.
+//! This module is only defined on Windows and allows receiving "ctrl-c",
+//! "ctrl-break", "ctrl-logoff", "ctrl-shutdown", and "ctrl-close"
+//! notifications. These events are listened for via the `SetConsoleCtrlHandler`
+//! function which receives the corresponding windows_sys event type.
-#![cfg(windows)]
+#![cfg(any(windows, docsrs))]
+#![cfg_attr(docsrs, doc(cfg(all(windows, feature = "signal"))))]
-use crate::signal::registry::{globals, EventId, EventInfo, Init, Storage};
use crate::signal::RxFuture;
-
-use std::convert::TryFrom;
use std::io;
-use std::sync::Once;
use std::task::{Context, Poll};
-use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE};
-use winapi::um::consoleapi::SetConsoleCtrlHandler;
-use winapi::um::wincon::{CTRL_BREAK_EVENT, CTRL_C_EVENT};
-
-#[derive(Debug)]
-pub(crate) struct OsStorage {
- ctrl_c: EventInfo,
- ctrl_break: EventInfo,
-}
-impl Init for OsStorage {
- fn init() -> Self {
- Self {
- ctrl_c: EventInfo::default(),
- ctrl_break: EventInfo::default(),
- }
- }
-}
-
-impl Storage for OsStorage {
- fn event_info(&self, id: EventId) -> Option<&EventInfo> {
- match DWORD::try_from(id) {
- Ok(CTRL_C_EVENT) => Some(&self.ctrl_c),
- Ok(CTRL_BREAK_EVENT) => Some(&self.ctrl_break),
- _ => None,
- }
- }
+#[cfg(not(docsrs))]
+#[path = "windows/sys.rs"]
+mod imp;
+#[cfg(not(docsrs))]
+pub(crate) use self::imp::{OsExtraData, OsStorage};
- fn for_each<'a, F>(&'a self, mut f: F)
- where
- F: FnMut(&'a EventInfo),
- {
- f(&self.ctrl_c);
- f(&self.ctrl_break);
- }
-}
-
-#[derive(Debug)]
-pub(crate) struct OsExtraData {}
-
-impl Init for OsExtraData {
- fn init() -> Self {
- Self {}
- }
-}
+#[cfg(docsrs)]
+#[path = "windows/stub.rs"]
+mod imp;
-/// Stream of events discovered via `SetConsoleCtrlHandler`.
-///
-/// This structure can be used to listen for events of the type `CTRL_C_EVENT`
-/// and `CTRL_BREAK_EVENT`. The `Stream` trait is implemented for this struct
-/// and will resolve for each notification received by the process. Note that
-/// there are few limitations with this as well:
-///
-/// * A notification to this process notifies *all* `Event` streams for that
-/// event type.
-/// * Notifications to an `Event` stream **are coalesced** if they aren't
-/// processed quickly enough. This means that if two notifications are
-/// received back-to-back, then the stream may only receive one item about the
-/// two notifications.
-#[must_use = "streams do nothing unless polled"]
-#[derive(Debug)]
-pub(crate) struct Event {
- inner: RxFuture,
-}
-
-impl Event {
- fn new(signum: DWORD) -> io::Result<Self> {
- global_init()?;
-
- let rx = globals().register_listener(signum as EventId);
-
- Ok(Self {
- inner: RxFuture::new(rx),
- })
- }
-}
-
-fn global_init() -> io::Result<()> {
- static INIT: Once = Once::new();
-
- 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(()))
-}
-
-unsafe extern "system" fn handler(ty: DWORD) -> BOOL {
- let globals = globals();
- globals.record_event(ty as EventId);
-
- // According to https://docs.microsoft.com/en-us/windows/console/handlerroutine
- // the handler routine is always invoked in a new thread, thus we don't
- // have the same restrictions as in Unix signal handlers, meaning we can
- // go ahead and perform the broadcast here.
- if globals.broadcast() {
- TRUE
- } else {
- // No one is listening for this notification any more
- // let the OS fire the next (possibly the default) handler.
- FALSE
- }
-}
-
-/// Creates a new stream which receives "ctrl-c" notifications sent to the
+/// Creates a new listener which receives "ctrl-c" notifications sent to the
/// process.
///
/// # Examples
@@ -137,12 +32,12 @@ unsafe extern "system" fn handler(ty: DWORD) -> BOOL {
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
-/// // An infinite stream of CTRL-C events.
-/// let mut stream = ctrl_c()?;
+/// // A listener of CTRL-C events.
+/// let mut signal = ctrl_c()?;
///
/// // Print whenever a CTRL-C event is received.
/// for countdown in (0..3).rev() {
-/// stream.recv().await;
+/// signal.recv().await;
/// println!("got CTRL-C. {} more to exit", countdown);
/// }
///
@@ -150,26 +45,32 @@ unsafe extern "system" fn handler(ty: DWORD) -> BOOL {
/// }
/// ```
pub fn ctrl_c() -> io::Result<CtrlC> {
- Event::new(CTRL_C_EVENT).map(|inner| CtrlC { inner })
+ Ok(CtrlC {
+ inner: self::imp::ctrl_c()?,
+ })
}
-/// Represents a stream which receives "ctrl-c" notifications sent to the process
+/// Represents a listener which receives "ctrl-c" notifications sent to the process
/// via `SetConsoleCtrlHandler`.
///
-/// A notification to this process notifies *all* streams listening for
+/// This event can be turned into a `Stream` using [`CtrlCStream`].
+///
+/// [`CtrlCStream`]: https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/struct.CtrlCStream.html
+///
+/// A notification to this process notifies *all* receivers for
/// this event. Moreover, the notifications **are coalesced** if they aren't processed
/// quickly enough. This means that if two notifications are received back-to-back,
-/// then the stream may only receive one item about the two notifications.
-#[must_use = "streams do nothing unless polled"]
+/// then the listener may only receive one item about the two notifications.
+#[must_use = "listeners do nothing unless polled"]
#[derive(Debug)]
pub struct CtrlC {
- inner: Event,
+ inner: RxFuture,
}
impl CtrlC {
/// Receives the next signal notification event.
///
- /// `None` is returned if no more events can be received by this stream.
+ /// `None` is returned if no more events can be received by the listener.
///
/// # Examples
///
@@ -178,12 +79,11 @@ impl CtrlC {
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
- /// // An infinite stream of CTRL-C events.
- /// let mut stream = ctrl_c()?;
+ /// let mut signal = ctrl_c()?;
///
/// // Print whenever a CTRL-C event is received.
/// for countdown in (0..3).rev() {
- /// stream.recv().await;
+ /// signal.recv().await;
/// println!("got CTRL-C. {} more to exit", countdown);
/// }
///
@@ -191,13 +91,13 @@ impl CtrlC {
/// }
/// ```
pub async fn recv(&mut self) -> Option<()> {
- self.inner.inner.recv().await
+ self.inner.recv().await
}
/// Polls to receive the next signal notification event, outside of an
/// `async` context.
///
- /// `None` is returned if no more events can be received by this stream.
+ /// `None` is returned if no more events can be received.
///
/// # Examples
///
@@ -223,27 +123,31 @@ impl CtrlC {
/// }
/// ```
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
- self.inner.inner.poll_recv(cx)
+ self.inner.poll_recv(cx)
}
}
-/// Represents a stream which receives "ctrl-break" notifications sent to the process
+/// Represents a listener which receives "ctrl-break" notifications sent to the process
/// via `SetConsoleCtrlHandler`.
///
-/// A notification to this process notifies *all* streams listening for
+/// This listener can be turned into a `Stream` using [`CtrlBreakStream`].
+///
+/// [`CtrlBreakStream`]: https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/struct.CtrlBreakStream.html
+///
+/// A notification to this process notifies *all* receivers for
/// this event. Moreover, the notifications **are coalesced** if they aren't processed
/// quickly enough. This means that if two notifications are received back-to-back,
-/// then the stream may only receive one item about the two notifications.
-#[must_use = "streams do nothing unless polled"]
+/// then the listener may only receive one item about the two notifications.
+#[must_use = "listeners do nothing unless polled"]
#[derive(Debug)]
pub struct CtrlBreak {
- inner: Event,
+ inner: RxFuture,
}
impl CtrlBreak {
/// Receives the next signal notification event.
///
- /// `None` is returned if no more events can be received by this stream.
+ /// `None` is returned if no more events can be received by this listener.
///
/// # Examples
///
@@ -252,24 +156,24 @@ impl CtrlBreak {
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
- /// // An infinite stream of CTRL-BREAK events.
- /// let mut stream = ctrl_break()?;
+ /// // A listener of CTRL-BREAK events.
+ /// let mut signal = ctrl_break()?;
///
/// // Print whenever a CTRL-BREAK event is received.
/// loop {
- /// stream.recv().await;
+ /// signal.recv().await;
/// println!("got signal CTRL-BREAK");
/// }
/// }
/// ```
pub async fn recv(&mut self) -> Option<()> {
- self.inner.inner.recv().await
+ self.inner.recv().await
}
/// Polls to receive the next signal notification event, outside of an
/// `async` context.
///
- /// `None` is returned if no more events can be received by this stream.
+ /// `None` is returned if no more events can be received by this listener.
///
/// # Examples
///
@@ -295,11 +199,11 @@ impl CtrlBreak {
/// }
/// ```
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
- self.inner.inner.poll_recv(cx)
+ self.inner.poll_recv(cx)
}
}
-/// Creates a new stream which receives "ctrl-break" notifications sent to the
+/// Creates a new listener which receives "ctrl-break" notifications sent to the
/// process.
///
/// # Examples
@@ -309,67 +213,312 @@ impl CtrlBreak {
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
-/// // An infinite stream of CTRL-BREAK events.
-/// let mut stream = ctrl_break()?;
+/// // A listener of CTRL-BREAK events.
+/// let mut signal = ctrl_break()?;
///
/// // Print whenever a CTRL-BREAK event is received.
/// loop {
-/// stream.recv().await;
+/// signal.recv().await;
/// println!("got signal CTRL-BREAK");
/// }
/// }
/// ```
pub fn ctrl_break() -> io::Result<CtrlBreak> {
- Event::new(CTRL_BREAK_EVENT).map(|inner| CtrlBreak { inner })
+ Ok(CtrlBreak {
+ inner: self::imp::ctrl_break()?,
+ })
}
-#[cfg(all(test, not(loom)))]
-mod tests {
- use super::*;
- use crate::runtime::Runtime;
+/// Creates a new listener which receives "ctrl-close" notifications sent to the
+/// process.
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// use tokio::signal::windows::ctrl_close;
+///
+/// #[tokio::main]
+/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
+/// // A listener of CTRL-CLOSE events.
+/// let mut signal = ctrl_close()?;
+///
+/// // Print whenever a CTRL-CLOSE event is received.
+/// for countdown in (0..3).rev() {
+/// signal.recv().await;
+/// println!("got CTRL-CLOSE. {} more to exit", countdown);
+/// }
+///
+/// Ok(())
+/// }
+/// ```
+pub fn ctrl_close() -> io::Result<CtrlClose> {
+ Ok(CtrlClose {
+ inner: self::imp::ctrl_close()?,
+ })
+}
- use tokio_test::{assert_ok, assert_pending, assert_ready_ok, task};
+/// Represents a listener which receives "ctrl-close" notitifications sent to the process
+/// via 'SetConsoleCtrlHandler'.
+///
+/// A notification to this process notifies *all* listeners listening for
+/// this event. Moreover, the notifications **are coalesced** if they aren't processed
+/// quickly enough. This means that if two notifications are received back-to-back,
+/// then the listener may only receive one item about the two notifications.
+#[must_use = "listeners do nothing unless polled"]
+#[derive(Debug)]
+pub struct CtrlClose {
+ inner: RxFuture,
+}
- #[test]
- fn ctrl_c() {
- let rt = rt();
- let _enter = rt.enter();
+impl CtrlClose {
+ /// Receives the next signal notification event.
+ ///
+ /// `None` is returned if no more events can be received by this listener.
+ ///
+ /// # Examples
+ ///
+ /// ```rust,no_run
+ /// use tokio::signal::windows::ctrl_close;
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// // A listener of CTRL-CLOSE events.
+ /// let mut signal = ctrl_close()?;
+ ///
+ /// // Print whenever a CTRL-CLOSE event is received.
+ /// signal.recv().await;
+ /// println!("got CTRL-CLOSE. Cleaning up before exiting");
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ pub async fn recv(&mut self) -> Option<()> {
+ self.inner.recv().await
+ }
- let mut ctrl_c = task::spawn(crate::signal::ctrl_c());
+ /// Polls to receive the next signal notification event, outside of an
+ /// `async` context.
+ ///
+ /// `None` is returned if no more events can be received by this listener.
+ ///
+ /// # Examples
+ ///
+ /// Polling from a manually implemented future
+ ///
+ /// ```rust,no_run
+ /// use std::pin::Pin;
+ /// use std::future::Future;
+ /// use std::task::{Context, Poll};
+ /// use tokio::signal::windows::CtrlClose;
+ ///
+ /// struct MyFuture {
+ /// ctrl_close: CtrlClose,
+ /// }
+ ///
+ /// impl Future for MyFuture {
+ /// type Output = Option<()>;
+ ///
+ /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ /// println!("polling MyFuture");
+ /// self.ctrl_close.poll_recv(cx)
+ /// }
+ /// }
+ /// ```
+ pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
+ self.inner.poll_recv(cx)
+ }
+}
- assert_pending!(ctrl_c.poll());
+/// Creates a new listener which receives "ctrl-shutdown" notifications sent to the
+/// process.
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// use tokio::signal::windows::ctrl_shutdown;
+///
+/// #[tokio::main]
+/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
+/// // A listener of CTRL-SHUTDOWN events.
+/// let mut signal = ctrl_shutdown()?;
+///
+/// signal.recv().await;
+/// println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
+///
+/// Ok(())
+/// }
+/// ```
+pub fn ctrl_shutdown() -> io::Result<CtrlShutdown> {
+ Ok(CtrlShutdown {
+ inner: self::imp::ctrl_shutdown()?,
+ })
+}
- // Windows doesn't have a good programmatic way of sending events
- // like sending signals on Unix, so we'll stub out the actual OS
- // integration and test that our handling works.
- unsafe {
- super::handler(CTRL_C_EVENT);
- }
+/// Represents a listener which receives "ctrl-shutdown" notitifications sent to the process
+/// via 'SetConsoleCtrlHandler'.
+///
+/// A notification to this process notifies *all* listeners listening for
+/// this event. Moreover, the notifications **are coalesced** if they aren't processed
+/// quickly enough. This means that if two notifications are received back-to-back,
+/// then the listener may only receive one item about the two notifications.
+#[must_use = "listeners do nothing unless polled"]
+#[derive(Debug)]
+pub struct CtrlShutdown {
+ inner: RxFuture,
+}
- assert_ready_ok!(ctrl_c.poll());
+impl CtrlShutdown {
+ /// Receives the next signal notification event.
+ ///
+ /// `None` is returned if no more events can be received by this listener.
+ ///
+ /// # Examples
+ ///
+ /// ```rust,no_run
+ /// use tokio::signal::windows::ctrl_shutdown;
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// // A listener of CTRL-SHUTDOWN events.
+ /// let mut signal = ctrl_shutdown()?;
+ ///
+ /// // Print whenever a CTRL-SHUTDOWN event is received.
+ /// signal.recv().await;
+ /// println!("got CTRL-SHUTDOWN. Cleaning up before exiting");
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ pub async fn recv(&mut self) -> Option<()> {
+ self.inner.recv().await
}
- #[test]
- fn ctrl_break() {
- let rt = rt();
+ /// Polls to receive the next signal notification event, outside of an
+ /// `async` context.
+ ///
+ /// `None` is returned if no more events can be received by this listener.
+ ///
+ /// # Examples
+ ///
+ /// Polling from a manually implemented future
+ ///
+ /// ```rust,no_run
+ /// use std::pin::Pin;
+ /// use std::future::Future;
+ /// use std::task::{Context, Poll};
+ /// use tokio::signal::windows::CtrlShutdown;
+ ///
+ /// struct MyFuture {
+ /// ctrl_shutdown: CtrlShutdown,
+ /// }
+ ///
+ /// impl Future for MyFuture {
+ /// type Output = Option<()>;
+ ///
+ /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ /// println!("polling MyFuture");
+ /// self.ctrl_shutdown.poll_recv(cx)
+ /// }
+ /// }
+ /// ```
+ pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
+ self.inner.poll_recv(cx)
+ }
+}
- rt.block_on(async {
- let mut ctrl_break = assert_ok!(super::ctrl_break());
+/// Creates a new listener which receives "ctrl-logoff" notifications sent to the
+/// process.
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// use tokio::signal::windows::ctrl_logoff;
+///
+/// #[tokio::main]
+/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
+/// // A listener of CTRL-LOGOFF events.
+/// let mut signal = ctrl_logoff()?;
+///
+/// signal.recv().await;
+/// println!("got CTRL-LOGOFF. Cleaning up before exiting");
+///
+/// Ok(())
+/// }
+/// ```
+pub fn ctrl_logoff() -> io::Result<CtrlLogoff> {
+ Ok(CtrlLogoff {
+ inner: self::imp::ctrl_logoff()?,
+ })
+}
- // Windows doesn't have a good programmatic way of sending events
- // like sending signals on Unix, so we'll stub out the actual OS
- // integration and test that our handling works.
- unsafe {
- super::handler(CTRL_BREAK_EVENT);
- }
+/// Represents a listener which receives "ctrl-logoff" notitifications sent to the process
+/// via 'SetConsoleCtrlHandler'.
+///
+/// A notification to this process notifies *all* listeners listening for
+/// this event. Moreover, the notifications **are coalesced** if they aren't processed
+/// quickly enough. This means that if two notifications are received back-to-back,
+/// then the listener may only receive one item about the two notifications.
+#[must_use = "listeners do nothing unless polled"]
+#[derive(Debug)]
+pub struct CtrlLogoff {
+ inner: RxFuture,
+}
- ctrl_break.recv().await.unwrap();
- });
+impl CtrlLogoff {
+ /// Receives the next signal notification event.
+ ///
+ /// `None` is returned if no more events can be received by this listener.
+ ///
+ /// # Examples
+ ///
+ /// ```rust,no_run
+ /// use tokio::signal::windows::ctrl_logoff;
+ ///
+ /// #[tokio::main]
+ /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// // An listener of CTRL-LOGOFF events.
+ /// let mut signal = ctrl_logoff()?;
+ ///
+ /// // Print whenever a CTRL-LOGOFF event is received.
+ /// signal.recv().await;
+ /// println!("got CTRL-LOGOFF. Cleaning up before exiting");
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ pub async fn recv(&mut self) -> Option<()> {
+ self.inner.recv().await
}
- fn rt() -> Runtime {
- crate::runtime::Builder::new_current_thread()
- .build()
- .unwrap()
+ /// Polls to receive the next signal notification event, outside of an
+ /// `async` context.
+ ///
+ /// `None` is returned if no more events can be received by this listener.
+ ///
+ /// # Examples
+ ///
+ /// Polling from a manually implemented future
+ ///
+ /// ```rust,no_run
+ /// use std::pin::Pin;
+ /// use std::future::Future;
+ /// use std::task::{Context, Poll};
+ /// use tokio::signal::windows::CtrlLogoff;
+ ///
+ /// struct MyFuture {
+ /// ctrl_logoff: CtrlLogoff,
+ /// }
+ ///
+ /// impl Future for MyFuture {
+ /// type Output = Option<()>;
+ ///
+ /// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ /// println!("polling MyFuture");
+ /// self.ctrl_logoff.poll_recv(cx)
+ /// }
+ /// }
+ /// ```
+ pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
+ self.inner.poll_recv(cx)
}
}
diff --git a/vendor/tokio/src/signal/windows/stub.rs b/vendor/tokio/src/signal/windows/stub.rs
new file mode 100644
index 000000000..61df30979
--- /dev/null
+++ b/vendor/tokio/src/signal/windows/stub.rs
@@ -0,0 +1,25 @@
+//! Stub implementations for the platform API so that rustdoc can build linkable
+//! documentation on non-windows platforms.
+
+use crate::signal::RxFuture;
+use std::io;
+
+pub(super) fn ctrl_break() -> io::Result<RxFuture> {
+ panic!()
+}
+
+pub(super) fn ctrl_close() -> io::Result<RxFuture> {
+ panic!()
+}
+
+pub(super) fn ctrl_c() -> io::Result<RxFuture> {
+ panic!()
+}
+
+pub(super) fn ctrl_logoff() -> io::Result<RxFuture> {
+ panic!()
+}
+
+pub(super) fn ctrl_shutdown() -> io::Result<RxFuture> {
+ panic!()
+}
diff --git a/vendor/tokio/src/signal/windows/sys.rs b/vendor/tokio/src/signal/windows/sys.rs
new file mode 100644
index 000000000..26e6bdf81
--- /dev/null
+++ b/vendor/tokio/src/signal/windows/sys.rs
@@ -0,0 +1,229 @@
+use std::io;
+use std::sync::Once;
+
+use crate::signal::registry::{globals, EventId, EventInfo, Init, Storage};
+use crate::signal::RxFuture;
+
+use windows_sys::Win32::Foundation::BOOL;
+use windows_sys::Win32::System::Console as console;
+
+pub(super) fn ctrl_break() -> io::Result<RxFuture> {
+ new(console::CTRL_BREAK_EVENT)
+}
+
+pub(super) fn ctrl_close() -> io::Result<RxFuture> {
+ new(console::CTRL_CLOSE_EVENT)
+}
+
+pub(super) fn ctrl_c() -> io::Result<RxFuture> {
+ new(console::CTRL_C_EVENT)
+}
+
+pub(super) fn ctrl_logoff() -> io::Result<RxFuture> {
+ new(console::CTRL_LOGOFF_EVENT)
+}
+
+pub(super) fn ctrl_shutdown() -> io::Result<RxFuture> {
+ new(console::CTRL_SHUTDOWN_EVENT)
+}
+
+fn new(signum: u32) -> io::Result<RxFuture> {
+ global_init()?;
+ let rx = globals().register_listener(signum as EventId);
+ Ok(RxFuture::new(rx))
+}
+
+#[derive(Debug)]
+pub(crate) struct OsStorage {
+ ctrl_break: EventInfo,
+ ctrl_close: EventInfo,
+ ctrl_c: EventInfo,
+ ctrl_logoff: EventInfo,
+ ctrl_shutdown: EventInfo,
+}
+
+impl Init for OsStorage {
+ fn init() -> Self {
+ Self {
+ ctrl_break: Default::default(),
+ ctrl_close: Default::default(),
+ ctrl_c: Default::default(),
+ ctrl_logoff: Default::default(),
+ ctrl_shutdown: Default::default(),
+ }
+ }
+}
+
+impl Storage for OsStorage {
+ fn event_info(&self, id: EventId) -> Option<&EventInfo> {
+ match u32::try_from(id) {
+ Ok(console::CTRL_BREAK_EVENT) => Some(&self.ctrl_break),
+ Ok(console::CTRL_CLOSE_EVENT) => Some(&self.ctrl_close),
+ Ok(console::CTRL_C_EVENT) => Some(&self.ctrl_c),
+ Ok(console::CTRL_LOGOFF_EVENT) => Some(&self.ctrl_logoff),
+ Ok(console::CTRL_SHUTDOWN_EVENT) => Some(&self.ctrl_shutdown),
+ _ => None,
+ }
+ }
+
+ fn for_each<'a, F>(&'a self, mut f: F)
+ where
+ F: FnMut(&'a EventInfo),
+ {
+ f(&self.ctrl_break);
+ f(&self.ctrl_close);
+ f(&self.ctrl_c);
+ f(&self.ctrl_logoff);
+ f(&self.ctrl_shutdown);
+ }
+}
+
+#[derive(Debug)]
+pub(crate) struct OsExtraData {}
+
+impl Init for OsExtraData {
+ fn init() -> Self {
+ Self {}
+ }
+}
+
+fn global_init() -> io::Result<()> {
+ static INIT: Once = Once::new();
+
+ let mut init = None;
+
+ INIT.call_once(|| unsafe {
+ let rc = console::SetConsoleCtrlHandler(Some(handler), 1);
+ let ret = if rc == 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ };
+
+ init = Some(ret);
+ });
+
+ init.unwrap_or_else(|| Ok(()))
+}
+
+unsafe extern "system" fn handler(ty: u32) -> BOOL {
+ let globals = globals();
+ globals.record_event(ty as EventId);
+
+ // According to https://docs.microsoft.com/en-us/windows/console/handlerroutine
+ // the handler routine is always invoked in a new thread, thus we don't
+ // have the same restrictions as in Unix signal handlers, meaning we can
+ // go ahead and perform the broadcast here.
+ if globals.broadcast() {
+ 1
+ } else {
+ // No one is listening for this notification any more
+ // let the OS fire the next (possibly the default) handler.
+ 0
+ }
+}
+
+#[cfg(all(test, not(loom)))]
+mod tests {
+ use super::*;
+ use crate::runtime::Runtime;
+
+ use tokio_test::{assert_ok, assert_pending, assert_ready_ok, task};
+
+ #[test]
+ fn ctrl_c() {
+ let rt = rt();
+ let _enter = rt.enter();
+
+ let mut ctrl_c = task::spawn(crate::signal::ctrl_c());
+
+ assert_pending!(ctrl_c.poll());
+
+ // Windows doesn't have a good programmatic way of sending events
+ // like sending signals on Unix, so we'll stub out the actual OS
+ // integration and test that our handling works.
+ unsafe {
+ super::handler(console::CTRL_C_EVENT);
+ }
+
+ assert_ready_ok!(ctrl_c.poll());
+ }
+
+ #[test]
+ fn ctrl_break() {
+ let rt = rt();
+
+ rt.block_on(async {
+ let mut ctrl_break = assert_ok!(crate::signal::windows::ctrl_break());
+
+ // Windows doesn't have a good programmatic way of sending events
+ // like sending signals on Unix, so we'll stub out the actual OS
+ // integration and test that our handling works.
+ unsafe {
+ super::handler(console::CTRL_BREAK_EVENT);
+ }
+
+ ctrl_break.recv().await.unwrap();
+ });
+ }
+
+ #[test]
+ fn ctrl_close() {
+ let rt = rt();
+
+ rt.block_on(async {
+ let mut ctrl_close = assert_ok!(crate::signal::windows::ctrl_close());
+
+ // Windows doesn't have a good programmatic way of sending events
+ // like sending signals on Unix, so we'll stub out the actual OS
+ // integration and test that our handling works.
+ unsafe {
+ super::handler(console::CTRL_CLOSE_EVENT);
+ }
+
+ ctrl_close.recv().await.unwrap();
+ });
+ }
+
+ #[test]
+ fn ctrl_shutdown() {
+ let rt = rt();
+
+ rt.block_on(async {
+ let mut ctrl_shutdown = assert_ok!(crate::signal::windows::ctrl_shutdown());
+
+ // Windows doesn't have a good programmatic way of sending events
+ // like sending signals on Unix, so we'll stub out the actual OS
+ // integration and test that our handling works.
+ unsafe {
+ super::handler(console::CTRL_SHUTDOWN_EVENT);
+ }
+
+ ctrl_shutdown.recv().await.unwrap();
+ });
+ }
+
+ #[test]
+ fn ctrl_logoff() {
+ let rt = rt();
+
+ rt.block_on(async {
+ let mut ctrl_logoff = assert_ok!(crate::signal::windows::ctrl_logoff());
+
+ // Windows doesn't have a good programmatic way of sending events
+ // like sending signals on Unix, so we'll stub out the actual OS
+ // integration and test that our handling works.
+ unsafe {
+ super::handler(console::CTRL_LOGOFF_EVENT);
+ }
+
+ ctrl_logoff.recv().await.unwrap();
+ });
+ }
+
+ fn rt() -> Runtime {
+ crate::runtime::Builder::new_current_thread()
+ .build()
+ .unwrap()
+ }
+}