mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-23 00:00:10 +02:00
signal: remember the result of SetConsoleCtrlHandler (#7833)
The unix implementation remembers whether it failed or not, so the windows implementation should do so as well. This PR also replaces the `(Once, AtomicState)` pair with `OnceLock` and tries to remember the original errno value.
This commit is contained in:
+17
-34
@@ -14,8 +14,7 @@ use crate::sync::watch;
|
||||
|
||||
use mio::net::UnixStream;
|
||||
use std::io::{self, Error, ErrorKind, Write};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Once;
|
||||
use std::sync::OnceLock;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "illumos")))]
|
||||
@@ -239,20 +238,10 @@ impl From<SignalKind> for std::os::raw::c_int {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct SignalInfo {
|
||||
event_info: EventInfo,
|
||||
init: Once,
|
||||
initialized: AtomicBool,
|
||||
}
|
||||
|
||||
impl Default for SignalInfo {
|
||||
fn default() -> SignalInfo {
|
||||
SignalInfo {
|
||||
event_info: EventInfo::default(),
|
||||
init: Once::new(),
|
||||
initialized: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
init: OnceLock<Result<(), Option<i32>>>,
|
||||
}
|
||||
|
||||
/// Our global signal handler for all signals registered by this module.
|
||||
@@ -294,26 +283,20 @@ fn signal_enable(signal: SignalKind, handle: &Handle) -> io::Result<()> {
|
||||
Some(slot) => slot,
|
||||
None => return Err(io::Error::new(io::ErrorKind::Other, "signal too large")),
|
||||
};
|
||||
let mut registered = Ok(());
|
||||
siginfo.init.call_once(|| {
|
||||
registered = unsafe {
|
||||
signal_hook_registry::register(signal, move || action(globals, signal)).map(|_| ())
|
||||
};
|
||||
if registered.is_ok() {
|
||||
siginfo.initialized.store(true, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
registered?;
|
||||
// If the call_once failed, it won't be retried on the next attempt to register the signal. In
|
||||
// such case it is not run, registered is still `Ok(())`, initialized is still `false`.
|
||||
if siginfo.initialized.load(Ordering::Relaxed) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Failed to register signal handler",
|
||||
))
|
||||
}
|
||||
|
||||
siginfo
|
||||
.init
|
||||
.get_or_init(|| {
|
||||
unsafe { signal_hook_registry::register(signal, move || action(globals, signal)) }
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.raw_os_error())
|
||||
})
|
||||
.map_err(|e| {
|
||||
e.map_or_else(
|
||||
|| Error::new(ErrorKind::Other, "registering signal handler failed"),
|
||||
Error::from_raw_os_error,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// An listener for receiving a particular type of OS signal.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::io;
|
||||
use std::sync::Once;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use crate::signal::registry::{globals, EventId, EventInfo, Storage};
|
||||
use crate::signal::RxFuture;
|
||||
@@ -85,22 +85,22 @@ impl Storage for OsStorage {
|
||||
pub(crate) struct OsExtraData {}
|
||||
|
||||
fn global_init() -> io::Result<()> {
|
||||
static INIT: Once = Once::new();
|
||||
static INIT: OnceLock<Result<(), Option<i32>>> = OnceLock::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())
|
||||
INIT.get_or_init(|| {
|
||||
let rc = unsafe { console::SetConsoleCtrlHandler(Some(handler), 1) };
|
||||
if rc == 0 {
|
||||
Err(io::Error::last_os_error().raw_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
init = Some(ret);
|
||||
});
|
||||
|
||||
init.unwrap_or_else(|| Ok(()))
|
||||
}
|
||||
})
|
||||
.map_err(|e| {
|
||||
e.map_or_else(
|
||||
|| io::Error::new(io::ErrorKind::Other, "registering signal handler failed"),
|
||||
io::Error::from_raw_os_error,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
unsafe extern "system" fn handler(ty: u32) -> BOOL {
|
||||
|
||||
Reference in New Issue
Block a user