How to Handle Signals in C: Simple Guide with Examples
In C, you handle signals by defining a
signal handler function and registering it with signal() for the desired signal. This lets your program respond to events like SIGINT (Ctrl+C) safely and cleanly.Why This Happens
Signals are asynchronous notifications sent to a program to notify it of events like interrupts or termination requests. If you don't handle signals properly, your program may terminate abruptly or behave unpredictably.
Here is an example of broken code that tries to handle SIGINT but uses an unsafe operation inside the handler.
c
#include <stdio.h> #include <signal.h> void handler(int sig) { printf("Caught signal %d\n", sig); // Unsafe in signal handler } int main() { signal(SIGINT, handler); while(1) {} return 0; }
Output
Caught signal 2
Caught signal 2
... (may crash or behave unpredictably)
The Fix
To fix signal handling, use a proper handler function with the correct signature (void handler(int)) and avoid unsafe functions like printf inside the handler. Instead, use write for output or set a flag to handle later.
Also, register the handler with signal() or better, sigaction() for more control.
c
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> volatile sig_atomic_t stop = 0; void handler(int sig) { const char msg[] = "Caught SIGINT, exiting...\n"; write(STDOUT_FILENO, msg, sizeof(msg) - 1); // Safe in signal handler stop = 1; // Set flag to stop main loop } int main() { if (signal(SIGINT, handler) == SIG_ERR) { perror("signal"); exit(EXIT_FAILURE); } while (!stop) { // Program work here } return 0; }
Output
Caught SIGINT, exiting...
Prevention
To avoid signal handling errors:
- Always use the correct handler signature:
void handler(int). - Avoid unsafe functions like
printfinside handlers; usewriteor set flags. - Prefer
sigaction()oversignal()for reliable behavior. - Keep handlers simple and fast to avoid unexpected behavior.
- Use
volatile sig_atomic_tfor flags shared between handler and main code.
Related Errors
Common related errors include:
- Using non-async-signal-safe functions inside handlers causing crashes.
- Not resetting the signal handler, leading to default termination.
- Ignoring signals that should be handled, causing resource leaks or stuck programs.
Key Takeaways
Use a proper signal handler function with signature void handler(int).
Avoid unsafe functions like printf inside signal handlers; use write or flags instead.
Register handlers with signal() or preferably sigaction() for better control.
Keep signal handlers simple and quick to avoid unexpected program behavior.
Use volatile sig_atomic_t variables to communicate between handlers and main code.