rune_modules/signal.rs
1//! The native `signal` module for the [Rune Language].
2//!
3//! [Rune Language]: https://rune-rs.github.io
4//!
5//! ## Usage
6//!
7//! Add the following to your `Cargo.toml`:
8//!
9//! ```toml
10//! rune-modules = { version = "0.14.1", features = ["signal"] }
11//! ```
12//!
13//! Install it into your context:
14//!
15//! ```rust
16//! let mut context = rune::Context::with_default_modules()?;
17//! context.install(rune_modules::signal::module(true)?)?;
18//! # Ok::<_, rune::support::Error>(())
19//! ```
20//!
21//! Use it in Rune:
22//!
23//! ```rust,ignore
24//! fn main() {
25//! signal::ctrl_c().await?;
26//! println("Exiting...");
27//! }
28//! ```
29
30// Documentation copied from the Tokio project under the MIT license.
31// See: https://github.com/tokio-rs/tokio/blob/master/LICENSE
32
33use std::io;
34
35use rune::{ContextError, Module};
36
37/// Construct the `signal` module.
38///
39/// # Tokio
40///
41/// This function is implemented using [Tokio], and requires the Tokio runtime
42/// to be in scope.
43///
44/// [Tokio]: https://tokio.rs
45#[rune::module(::signal)]
46pub fn module(_stdio: bool) -> Result<Module, ContextError> {
47 let mut module = Module::from_meta(self::module_meta)?;
48 module.function_meta(ctrl_c)?;
49 Ok(module)
50}
51
52/// Completes when a "ctrl-c" notification is sent to the process.
53///
54/// While signals are handled very differently between Unix and Windows, both
55/// platforms support receiving a signal on "ctrl-c". This function provides a
56/// portable API for receiving this notification.
57///
58/// Once the returned future is polled, a listener is registered. The future
59/// will complete on the first received `ctrl-c` **after** the initial call to
60/// either `Future::poll` or `.await`.
61///
62/// # Caveats
63///
64/// On Unix platforms, the first time that a `Signal` instance is registered for
65/// a particular signal kind, an OS signal-handler is installed which replaces
66/// the default platform behavior when that signal is received, **for the
67/// duration of the entire process**.
68///
69/// For example, Unix systems will terminate a process by default when it
70/// receives a signal generated by "CTRL+C" on the terminal. But, when a
71/// `ctrl_c` stream is created to listen for this signal, the time it arrives,
72/// it will be translated to a stream event, and the process will continue to
73/// execute. **Even if this `Signal` instance is dropped, subsequent SIGINT
74/// deliveries will end up captured by Tokio, and the default platform behavior
75/// will NOT be reset**.
76///
77/// Thus, applications should take care to ensure the expected signal behavior
78/// occurs as expected after listening for specific signals.
79///
80/// # Examples
81///
82/// ```rune,no_run
83/// pub async fn main() {
84/// println!("Waiting for ctrl-c");
85/// signal::ctrl_c().await?;
86/// println!("Received ctrl-c event");
87/// }
88/// ```
89#[rune::function]
90async fn ctrl_c() -> io::Result<()> {
91 tokio::signal::ctrl_c().await
92}