From 808aabbd17bb8c760380fbde5b6addaea68ed4ff Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Sun, 16 May 2021 17:20:59 +0200 Subject: [PATCH] Use simpler example in readme --- README.md | 89 +++++-------------------------------------------------- 1 file changed, 7 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 94140dc..71a3d27 100644 --- a/README.md +++ b/README.md @@ -39,91 +39,16 @@ each time). ```rust use std::io::Error; use std::sync::Arc; -use std::sync::atomic::AtomicBool; - -use signal_hook::consts::signal::*; -use signal_hook::consts::TERM_SIGNALS; -use signal_hook::flag; -// A friend of the Signals iterator, but can be customized by what we want yielded about each -// signal. -use signal_hook::iterator::SignalsInfo; -use signal_hook::iterator::exfiltrator::WithOrigin; -use signal_hook::low_level; +use std::sync::atomic::{AtomicBool, Ordering}; fn main() -> Result<(), Error> { - // Make sure double CTRL+C and similar kills - let term_now = Arc::new(AtomicBool::new(false)); - for sig in TERM_SIGNALS { - // When terminated by a second term signal, exit with exit code 1. - // This will do nothing the first time (because term_now is false). - flag::register_conditional_shutdown(*sig, 1, Arc::clone(&term_now))?; - // But this will "arm" the above for the second time, by setting it to true. - // The order of registering these is important, if you put this one first, it will - // first arm and then terminate ‒ all in the first round. - flag::register(*sig, Arc::clone(&term_now))?; + let term = Arc::new(AtomicBool::new(false)); + signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&term))?; + while !term.load(Ordering::Relaxed) { + // Do some time-limited stuff here + // (if this could block forever, then there's no guarantee the signal will have any + // effect). } - - // Subscribe to all these signals with information about where they come from. We use the - // extra info only for logging in this example (it is not available on all the OSes or at - // all the occasions anyway, it may return `Unknown`). - let mut sigs = vec![ - // Some terminal handling - SIGTSTP, SIGCONT, SIGWINCH, - // Reload of configuration for daemons ‒ um, is this example for a TUI app or a daemon - // O:-)? You choose... - SIGHUP, - // Application-specific action, to print some statistics. - SIGUSR1, - ]; - sigs.extend(TERM_SIGNALS); - let mut signals = SignalsInfo::::new(&sigs)?; - - // This is the actual application that'll start in its own thread. We'll control it from - // this thread based on the signals, but it keeps running. - // This is called after all the signals got registered, to avoid the short race condition - // in the first registration of each signal in multi-threaded programs. - let app = App::run_background(); - - // Consume all the incoming signals. This happens in "normal" Rust thread, not in the - // signal handlers. This means that we are allowed to do whatever we like in here, without - // restrictions, but it also means the kernel believes the signal already got delivered, we - // handle them in delayed manner. This is in contrast with eg the above - // `register_conditional_shutdown` where the shutdown happens *inside* the handler. - let mut has_terminal = true; - for info in &mut signals { - // Will print info about signal + where it comes from. - eprintln!("Received a signal {:?}", info); - match info.signal { - SIGTSTP => { - // Restore the terminal to non-TUI mode - if has_terminal { - app.restore_term(); - has_terminal = false; - // And actually stop ourselves, by a little trick. - low_level::raise(SIGSTOP)?; - } - } - SIGCONT => { - if !has_terminal { - app.claim_term(); - has_terminal = true; - } - } - SIGWINCH => app.resize_term(), - SIGHUP => app.reload_config(), - SIGUSR1 => app.print_stats(), - term_sig => { // These are all the ones left - eprintln!("Terminating"); - assert!(TERM_SIGNALS.contains(&term_sig)); - break; - } - } - } - - // If during this another termination signal comes, the trick at the top would kick in and - // terminate early. But if it doesn't, the application shuts down gracefully. - app.wait_for_stop(); - Ok(()) } ```