[][src]Function signal_hook::register

pub unsafe fn register<F>(signal: i32, action: F) -> Result<SigId, Error> where
    F: Fn() + Sync + Send + 'static, 

Registers an arbitrary action for the given signal.

This makes sure there's a signal handler for the given signal. It then adds the action to the ones called each time the signal is delivered. If multiple actions are set for the same signal, all are called, in the order of registration.

If there was a previous signal handler for the given signal, it is chained ‒ it will be called as part of this library's signal handler, before any actions set through this function.

On success, the function returns an ID that can be used to remove the action again with unregister.

Panics

If the signal is one of (see FORBIDDEN):

  • SIGKILL
  • SIGSTOP
  • SIGILL
  • SIGFPE
  • SIGSEGV

The first two are not possible to override (and the underlying C functions simply ignore all requests to do so, which smells of possible bugs, or return errors). The rest can be set, but generally needs very special handling to do so correctly (direct manipulation of the application's address space, longjmp and similar). Unless you know very well what you're doing, you'll shoot yourself into the foot and this library won't help you with that.

Errors

Since the library manipulates signals using the low-level C functions, all these can return errors. Generally, the errors mean something like the specified signal does not exist on the given platform ‒ ofter a program is debugged and tested on a given OS, it should never return an error.

However, if an error is returned, there are no guarantees if the given action was registered or not.

Unsafety

This function is unsafe, because the action is run inside a signal handler. The set of functions allowed to be called from within is very limited (they are called signal-safe functions by POSIX). These specifically do not contain mutexes and memory allocation/deallocation. They do contain routines to terminate the program, to further manipulate signals (by the low-level functions, not by this library) and to read and write file descriptors. Calling program's own functions consisting only of these is OK, as is manipulating program's variables ‒ however, as the action can be called on any thread that does not have the given signal masked (by default no signal is masked on any thread), and mutexes are a no-go, this is harder than it looks like at first.

As panicking from within a signal handler would be a panic across FFI boundary (which is undefined behavior), the passed handler must not panic.

If you find these limitations hard to satisfy, choose from the helper functions in submodules of this library ‒ these provide safe interface to use some common signal handling patters.

Race condition

Currently, there's a short race condition. If this is the first action for the given signal, there was another signal handler previously and the signal comes into a different thread during this function, it can happen the original handler is not chained in this one instance.

This is considered unimportant problem, since most programs install their signal handlers during startup, before the signals effectively do anything. If you want to avoid the race condition completely, initialize all signal handling before starting any threads.

Performance

Even when it is possible to repeatedly install and remove actions during the lifetime of a program, the installation and removal is considered a slow operation and should not be done very often. Also, there's limited (though huge) amount of distinct IDs (they are u64).

Examples

extern crate signal_hook;

use std::io::Error;
use std::process;

fn main() -> Result<(), Error> {
    let signal = unsafe { signal_hook::register(signal_hook::SIGTERM, || process::abort()) }?;
    // Stuff here...
    signal_hook::unregister(signal); // Not really necessary.
    Ok(())
}