aboutsummaryrefslogtreecommitdiff
path: root/src/signal/unix.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/signal/unix.rs')
-rw-r--r--src/signal/unix.rs98
1 files changed, 74 insertions, 24 deletions
diff --git a/src/signal/unix.rs b/src/signal/unix.rs
index 86ea9a9..0e1329e 100644
--- a/src/signal/unix.rs
+++ b/src/signal/unix.rs
@@ -6,6 +6,8 @@
#![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;
@@ -17,18 +19,19 @@ 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()
}
}
@@ -48,7 +51,7 @@ impl Storage for OsStorage {
#[derive(Debug)]
pub(crate) struct OsExtraData {
sender: UnixStream,
- receiver: UnixStream,
+ pub(crate) receiver: UnixStream,
}
impl Init for OsExtraData {
@@ -60,7 +63,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 {
@@ -80,15 +83,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)
}
@@ -96,7 +110,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)
}
@@ -104,7 +118,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)
}
@@ -119,7 +133,7 @@ impl SignalKind {
target_os = "netbsd",
target_os = "openbsd"
))]
- pub fn info() -> Self {
+ pub const fn info() -> Self {
Self(libc::SIGINFO)
}
@@ -127,7 +141,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)
}
@@ -135,7 +149,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)
}
@@ -144,7 +158,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)
}
@@ -153,7 +167,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)
}
@@ -161,7 +175,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)
}
@@ -169,7 +183,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)
}
@@ -177,7 +191,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)
}
@@ -185,11 +199,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,
@@ -357,8 +383,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),
@@ -380,6 +413,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
@@ -474,4 +513,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 _);
+ }
}