C signal handling
| C standard library (libc) |
|---|
| General topics |
| Miscellaneous headers |
In the C Standard Library, signal processing defines how a program handles various signals while it executes. A signal can report some exceptional behavior within the program (such as division by zero), or a signal can report some asynchronous event outside the program (such as someone striking an interactive attention key on a keyboard).
Standard signals
[edit]The C standard defines only 6 signals. They are all defined in signal.h header (csignal header in C++):[1]
SIGABRT– "abort", abnormal termination.SIGFPE– floating point exception.SIGILL– "illegal", invalid instruction.SIGINT– "interrupt", interactive attention request sent to the program.SIGSEGV– "segmentation violation", invalid memory access.SIGTERM– "terminate", termination request sent to the program.
Additional signals may be specified in the signal.h header by the implementation. For example, Unix and Unix-like operating systems (such as Linux) define more than 15 additional signals; see Unix signal.[2]
Debugging
[edit]SIGTRAPfor debugging purposes. It's platform-dependent and may be used on Unix-like operating systems.
Handling
[edit]A signal can be generated by calling raise() or kill() system calls. raise() sends a signal to the current process, kill() sends a signal to a specific process.
A signal handler is a function which is called by the target environment when the corresponding signal occurs. The target environment suspends execution of the program until the signal handler returns or calls longjmp().
Signal handlers can be set with signal() or sigaction(). The behavior of signal() has been changed multiple times across history and its use is discouraged.[3] It is only portable when used to set a signal's disposition to SIG_DFL or SIG_IGN. Signal handlers can be specified for all but two signals (SIGKILL and SIGSTOP cannot be caught, blocked or ignored).
If the signal reports an error within the program (and the signal is not asynchronous), the signal handler can terminate by calling abort(), exit(), or longjmp().
Functions
[edit]| Function | Description |
|---|---|
raise
|
artificially sends a signal to the calling process |
kill
|
artificially sends a signal to a specified process |
signal
|
sets the action taken when the program receives a specific signal |
Example usage
[edit]#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
volatile sig_atomic_t status = 0;
static void catch_function(int signo) {
status = signo;
}
int main(void) {
// Set above function as signal handler for the SIGINT signal:
if (signal(SIGINT, catch_function) == SIG_ERR) {
fprintf("An error occurred while setting a signal handler.\n", stderr);
return EXIT_FAILURE;
}
printf("Raising the interactive attention signal.");
if (raise(SIGINT)) {
fprintf("Error raising the signal.\n", stderr);
return EXIT_FAILURE;
}
if (status == SIGINT) {
printf("Interactive attention signal caught.");
}
printf("Exiting.");
return EXIT_SUCCESS;
// exiting after raising signal
}
Other languages
[edit]C++
[edit]C signals are traditionally used the same way in C++ as in C. However, one can also write wrappers for RAII-style usage.
export module org.wikipedia.example;
import <csignal>; // necessary to obtain macros
import std;
using std::function;
export namespace org::wikipedia::example {
class Signal {
private:
using Handler = function<void(int)>;
int sig;
public:
static constexpr int ABRT = SIGABRT;
static constexpr int FPE = SIGFPE;
static constexpr int ILL = SIGILL;
static constexpr int INT = SIGINT;
static constexpr int SEGV = SIGSEGV;
static constexpr int TERM = SIGTERM;
static constexpr int DFL = SIGDFL;
static constexpr int IGN = SIGIGN;
static constexpr int ERR = SIGERR;
explicit Signal(int sig):
sig{sig} {}
[[nodiscard]]
int getSignal() const noexcept {
return sig;
}
Handler handle(Handler handler) {
return std::signal(sig, handler);
}
int raise() {
return std::raise(sig);
}
};
}
This can also be done with Boost, using the class boost::asio::signal_set.
C#
[edit]C signals can be used with P/Invoke and Mono.Unix.Native.Syscall.
Java
[edit]C signals are usable in Java language, from module jdk.unsupported, with class sun.misc.Signal and interface sun.misc.SignalHandler.[4]
package org.wikipedia.example;
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class Example {
public static void main(String[] args) {
SignalHandler handler = new SignalHandler() {
public void handle(Signal sig) {
boolean handled = handlers.get(type).handle(type);
if (!handled) {
if (type.getDefaultAction() == SignalType.DefaultAction.IGNORE) {
SignalHandler.SIG_IGN.handle(sig);
} else {
SignalHandler.SIG_DFL.handle(sig);
}
}
}
};
Signal.handle(new Signal("INT"), handler);
}
}
Rust
[edit]Signals can be used with the signal_hook crate in Rust.[5]
use std::process;
use std::thread;
use std::time::Duration;
use signal_hook::consts::signal::*;
use signal_hook::iterator::Signals;
fn main() {
let mut signals: Signals = Signals::new(&[SIGINT, SIGTERM]).expect("Failed to set up signal handling");
thread::spawn(move || {
for signal in signals.forever() {
match signal {
SIGINT => {
println!("Received SIGINT (Ctrl+C). Exiting gracefully.");
process::exit(0);
}
SIGTERM => {
println!("Received SIGTERM. Exiting gracefully.");
process::exit(0);
}
_ => unreachable!(),
}
}
});
loop {
println!("Running...");
thread::sleep(Duration::from_secs(2));
}
}
See also
[edit]References
[edit]- ^ ISO/IEC 9899:1999 specification (PDF). p. 258, § 7.14 Signal handling.
- ^ "The Open Group Base Specifications Issue 6 – signal.h – signals". Retrieved 10 January 2012.
- ^ https://man7.org/linux/man-pages/man2/signal.2.html Signal(2) manpage
- ^ "Signal (Java Platform SE 9)". cr.openjdk.org. OpenJDK. Retrieved 10 October 2025.
- ^ "signal_hook - Rust". docs.rs. 9 May 2025.