Linux Signals: Custom Ctrl+C Handler (Short Practical Guide)
In Linux/embedded Linux, signals are useful for lightweight control events. Typical use: stop, reload, notify, timeout.
This example shows:
- Custom
Ctrl+C(SIGINT) behavior - Sending
SIGUSR1to another process - Using
SIGALRMas a timeout
Full short example
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define W(msg) write(STDOUT_FILENO, msg, sizeof(msg) - 1)
static volatile sig_atomic_t running = 1;
static volatile sig_atomic_t got_usr1 = 0;
static volatile sig_atomic_t child_pid = -1;
static void on_sigint(int sig) {
(void)sig;
W("\nSIGINT: Ctrl+C caught. Sending SIGUSR1 to child and setting 3s alarm...\n");
if (child_pid > 0) {
kill((pid_t)child_pid, SIGUSR1);
}
alarm(3); // after 3 seconds, SIGALRM will arrive
}
static void on_sigusr1(int sig) {
(void)sig;
got_usr1 = 1;
}
static void on_sigalrm(int sig) {
(void)sig;
W("SIGALRM: timeout reached, exiting now.\n");
running = 0;
}
int main(void) {
struct sigaction sa_int = {0}, sa_usr1 = {0}, sa_alrm = {0};
sa_int.sa_handler = on_sigint;
sigemptyset(&sa_int.sa_mask);
sigaction(SIGINT, &sa_int, NULL);
sa_usr1.sa_handler = on_sigusr1;
sigemptyset(&sa_usr1.sa_mask);
sigaction(SIGUSR1, &sa_usr1, NULL);
sa_alrm.sa_handler = on_sigalrm;
sigemptyset(&sa_alrm.sa_mask);
sigaction(SIGALRM, &sa_alrm, NULL);
pid_t pid = fork();
if (pid < 0) {
perror("fork");
return 1;
}
if (pid == 0) {
// child process
while (1) {
pause();
if (got_usr1) {
got_usr1 = 0;
W("Child: got SIGUSR1 from parent.\n");
}
}
}
// parent process
child_pid = pid;
printf("Parent PID=%d, Child PID=%d\n", getpid(), pid);
printf("Press Ctrl+C to trigger custom SIGINT behavior.\n");
while (running) {
pause();
}
kill(pid, SIGTERM);
return 0;
}
Build and run
gcc -Wall -Wextra -O2 signals_demo.c -o signals_demo
./signals_demo
Press Ctrl+C:
- Parent catches
SIGINT - Parent sends
SIGUSR1to child - Child prints a message
- After 3s,
SIGALRMends parent
Embedded Linux notes
- Signals are good for control events, not bulk data.
- Keep handlers minimal (set flags, write short message).
- Do real work in main loop, not inside handler.