A signal handler determines what a process does when a signal arrives. Without a custom handler, many signals terminate the process. A custom handler can instead give an application a chance to shut down cleanly—for example, by closing network connections or finishing pending writes. section 12.5.1 section 12.6
Keep the handler quick and simple. It receives the signal number, but not the application state needed for cleanup. It can also block another signal of the same type while it runs. A practical pattern is to have the handler set a global Boolean flag; the main loop checks that flag and performs cleanup in its normal context. section 12.6 section 12.12
To wire up that pattern in Rust:
- Define a handler with the signature fn(i32) -> (): it takes the signal number and returns nothing. section 12.6
- Register it with libc::signal() for the signal you want to handle. Do this early, before the main loop starts. section 12.6.2
- Use a mutable static for the shared shutdown flag, and access it within unsafe blocks. Let the main loop respond when it sees the flag. section 12.12 section 12.6.2
Responding to SIGTERM
A small program registers handlers, prints its progress in a loop, and raises signals to test them. Its SIGTERM handler changes a global shutdown flag. On the next loop check, the program sees the flag and exits through its own code rather than relying on SIGTERM’s default termination. section 12.6.2
Listing 12.12 Ignoring signals with libc::SIG_IGN
1 use libc::{signal,raise};
2 use libc::{SIG_DFL, SIG_IGN, SIGTERM};
3
4 fn main() {
5 unsafe { #1
6 signal(SIGTERM, SIG_IGN); #2
7 raise(SIGTERM); #3
8 }
9
10 println!("ok");
11
12 unsafe {
13 signal(SIGTERM, SIG_DFL); #4
14 raise(SIGTERM); #5
15 }
16
17 println!("not ok"); #6
18 }
A handler need not be a function: this listing passes SIG_IGN to libc::signal() to ignore SIGTERM, then passes SIG_DFL to restore its default behavior. SIGSTOP and SIGKILL cannot be ignored this way. section 12.8



