C++ Signal Handling – Capture and Respond to OS-Level Interrupts
Introduction – Why Signal Handling Matters in C++
C++ applications often run in environments where external interrupts or unexpected conditions—like Ctrl+C, segmentation faults, or timer expirations—can occur. Signal handling allows your program to intercept and react to such events gracefully, instead of crashing or behaving unpredictably.
In this guide, you’ll learn:
- What signals are in C++
- How to use
signal()and define signal handlers - Common signal types (
SIGINT,SIGSEGV,SIGTERM) - Best practices for safe and clean signal management
What Is Signal Handling?
A signal is a notification sent to a process by the operating system or another process to indicate an event. Signal handling lets you define a custom function (handler) to respond when a signal is received.
Code Example – With Output
Example: Handling Ctrl+C Interrupt (SIGINT)
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "\nInterrupt signal (" << signum << ") received.\n";
// Cleanup and exit
exit(signum);
}
int main() {
signal(SIGINT, signalHandler); // Handle Ctrl+C
while (1) {
cout << "Running...\n";
sleep(1);
}
return 0;
}
Output when Ctrl+C is pressed:
Running...
Running...
Interrupt signal (2) received.
Common C++ Signals
| Signal | Value | Description |
|---|---|---|
SIGINT | 2 | Interrupt from keyboard (Ctrl+C) |
SIGTERM | 15 | Termination signal |
SIGABRT | 6 | Abnormal termination (e.g., abort()) |
SIGSEGV | 11 | Invalid memory access (segfault) |
SIGFPE | 8 | Floating point error (e.g., divide by 0) |
SIGILL | 4 | Illegal instruction |
Using signal() Function
void signal(int signum, void (*handler)(int));
signum: The signal number (e.g.,SIGINT)handler: Function to handle the signal
Handling SIGFPE (Divide by Zero)
#include <csignal>
#include <iostream>
using namespace std;
void handler(int signum) {
cout << "Floating point exception (divide by zero)!\n";
exit(signum);
}
int main() {
signal(SIGFPE, handler);
int a = 1 / 0; // Triggers SIGFPE
}
Note: Behavior may vary by system/compiler. Use with caution.
Safe Signal Handling Practices
- Keep signal handlers short and simple
- Avoid using non-reentrant functions like
printf(usewrite()instead) - Use
volatile sig_atomic_tfor shared variables accessed in signal handlers
Summary Table – signal() vs raise()
| Function | Purpose |
|---|---|
signal() | Registers a signal handler |
raise() | Sends a signal to the current process |
kill(pid, x) | Sends signal x to another process with PID |
Best Practices & Tips
Best Practice: Use signal handlers for graceful shutdowns, not complex logic.
Tip: Combine signal handling with atexit() to ensure cleanup functions run.
Pitfall: Avoid calling malloc, printf, or new inside signal handlers—they may not be safe.
Use Cases for Signal Handling
Interrupt Handling: Gracefully stop on Ctrl+C
Logging Failures: Capture segmentation faults for diagnostics
Process Cleanup: Close files, deallocate memory on SIGTERM
Watchdog Systems: Reset logic on certain fault conditions
Secure Applications: Control sensitive operations on abnormal exit
Summary – Recap & Next Steps
Key Takeaways:
- Signals let you intercept OS-level events like interrupts or segmentation faults
- Use
signal()to define handlers - Keep handlers simple and clean to avoid unsafe behavior
Real-World Relevance:
Used in daemons, CLI tools, background services, embedded systems, and fault-tolerant enterprise software.
Next Steps:
- Learn about C++ Dynamic Memory Management
- Understand how to manage heap memory using
new,delete, andsmart pointers
FAQ – C++ Signal Handling
What is a signal in C++?
A signal is a message sent to a process to notify it of an event (e.g., SIGINT on Ctrl+C).
Can all signals be caught?
No. Some signals like SIGKILL and SIGSTOP cannot be caught or ignored.
What happens if no handler is defined?
Default behavior (usually termination) is executed by the OS.
Can I handle multiple signals?
Yes. You can register different handlers for each signal.
Is signal() portable across systems?
It’s standardized but may behave differently across Unix, Linux, and Windows.
