@@ -39,91 +39,16 @@ each time).
39
39
``` rust
40
40
use std :: io :: Error ;
41
41
use std :: sync :: Arc ;
42
- use std :: sync :: atomic :: AtomicBool ;
43
-
44
- use signal_hook :: consts :: signal :: * ;
45
- use signal_hook :: consts :: TERM_SIGNALS ;
46
- use signal_hook :: flag;
47
- // A friend of the Signals iterator, but can be customized by what we want yielded about each
48
- // signal.
49
- use signal_hook :: iterator :: SignalsInfo ;
50
- use signal_hook :: iterator :: exfiltrator :: WithOrigin ;
51
- use signal_hook :: low_level;
42
+ use std :: sync :: atomic :: {AtomicBool , Ordering };
52
43
53
44
fn main () -> Result <(), Error > {
54
- // Make sure double CTRL+C and similar kills
55
- let term_now = Arc :: new (AtomicBool :: new (false ));
56
- for sig in TERM_SIGNALS {
57
- // When terminated by a second term signal, exit with exit code 1.
58
- // This will do nothing the first time (because term_now is false).
59
- flag :: register_conditional_shutdown (* sig , 1 , Arc :: clone (& term_now ))? ;
60
- // But this will "arm" the above for the second time, by setting it to true.
61
- // The order of registering these is important, if you put this one first, it will
62
- // first arm and then terminate ‒ all in the first round.
63
- flag :: register (* sig , Arc :: clone (& term_now ))? ;
64
- }
65
-
66
- // Subscribe to all these signals with information about where they come from. We use the
67
- // extra info only for logging in this example (it is not available on all the OSes or at
68
- // all the occasions anyway, it may return `Unknown`).
69
- let mut sigs = vec! [
70
- // Some terminal handling
71
- SIGTSTP , SIGCONT , SIGWINCH ,
72
- // Reload of configuration for daemons ‒ um, is this example for a TUI app or a daemon
73
- // O:-)? You choose...
74
- SIGHUP ,
75
- // Application-specific action, to print some statistics.
76
- SIGUSR1 ,
77
- ];
78
- sigs . extend (TERM_SIGNALS );
79
- let mut signals = SignalsInfo :: <WithOrigin >:: new (& sigs )? ;
80
-
81
- // This is the actual application that'll start in its own thread. We'll control it from
82
- // this thread based on the signals, but it keeps running.
83
- // This is called after all the signals got registered, to avoid the short race condition
84
- // in the first registration of each signal in multi-threaded programs.
85
- let app = App :: run_background ();
86
-
87
- // Consume all the incoming signals. This happens in "normal" Rust thread, not in the
88
- // signal handlers. This means that we are allowed to do whatever we like in here, without
89
- // restrictions, but it also means the kernel believes the signal already got delivered, we
90
- // handle them in delayed manner. This is in contrast with eg the above
91
- // `register_conditional_shutdown` where the shutdown happens *inside* the handler.
92
- let mut has_terminal = true ;
93
- for info in & mut signals {
94
- // Will print info about signal + where it comes from.
95
- eprintln! (" Received a signal {:?}" , info );
96
- match info . signal {
97
- SIGTSTP => {
98
- // Restore the terminal to non-TUI mode
99
- if has_terminal {
100
- app . restore_term ();
101
- has_terminal = false ;
102
- // And actually stop ourselves, by a little trick.
103
- low_level :: raise (SIGSTOP )? ;
104
- }
105
- }
106
- SIGCONT => {
107
- if ! has_terminal {
108
- app . claim_term ();
109
- has_terminal = true ;
110
- }
111
- }
112
- SIGWINCH => app . resize_term (),
113
- SIGHUP => app . reload_config (),
114
- SIGUSR1 => app . print_stats (),
115
- term_sig => { // These are all the ones left
116
- eprintln! (" Terminating" );
117
- assert! (TERM_SIGNALS . contains (& term_sig ));
118
- break ;
119
- }
120
- }
45
+ let term = Arc :: new (AtomicBool :: new (false ));
46
+ signal_hook :: flag :: register (signal_hook :: consts :: SIGTERM , Arc :: clone (& term ))? ;
47
+ while ! term . load (Ordering :: Relaxed ) {
48
+ // Do some time-limited stuff here
49
+ // (if this could block forever, then there's no guarantee the signal will have any
50
+ // effect).
121
51
}
122
-
123
- // If during this another termination signal comes, the trick at the top would kick in and
124
- // terminate early. But if it doesn't, the application shuts down gracefully.
125
- app . wait_for_stop ();
126
-
127
52
Ok (())
128
53
}
129
54
```
0 commit comments