Signal Handlers in C

What are Signals in C?

A signal is a limited form of inter-process communication that can notify a process of an event or exception. Signals can be sent by the operating system or other processes to inform a program that something significant has occurred.

For example:

  • When a user presses Ctrl+C, a SIGINT signal is sent to the process.
  • If the system is running out of memory, it may send the SIGSEGV signal to notify the program of a segmentation fault.

When a signal is delivered to a process, it interrupts the normal execution flow and can either be caught, ignored, or cause the process to terminate, depending on how the signal is handled.

Common Signals in C

Signal Description
SIGINT Interrupt from keyboard (Ctrl+C)
SIGTERM Termination request
SIGKILL Kill signal
SIGSEGV Invalid memory reference
SIGFPE Floating-point exception
SIGILL Illegal instruction
SIGABRT Abort signal from abort()
SIGSTOP Stop the process (cannot be caught or ignored).

Signal Handling Basics

When a signal is sent to a process, the default behavior is triggered unless the process has registered a handler. A signal handler is a special function that allows the program to respond to the signal. For example, if you receive a SIGINT signal, you might want to perform cleanup before exiting the program.

The default actions for signals vary:

  • Termination signals (e.g., SIGINT, SIGTERM) cause the process to terminate.
  • Stop signals (e.g., SIGSTOP) stop the process until it is resumed.
  • Ignored signals (e.g., SIGCHLD) are handled in a special way depending on the system and are not acted on.

Using the signal() Function

In C, the signal() function is used to define a signal handler for a specific signal. Its syntax is as follows:

void (*signal(int sig, void (*func)(int)))(int);
  • sig: The signal to be handled (e.g., SIGINT).
  • func: A pointer to the function that will handle the signal.

If signal() is successful, it returns the previous handler for that signal. If it fails, it returns SIG_ERR.

advertisement

Example: Handling SIGINT with signal()

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
void sanfoundryHandler(int signal) {
    printf("\nSignal received: %d\n", signal);
    printf("Sanfoundry: Handling Ctrl+C gracefully!\n");
}
 
int main() {
    signal(SIGINT, sanfoundryHandler);  // Handle Ctrl+C
 
    while (1) {
        printf("Running... Press Ctrl+C to test signal handling\n");
        sleep(2);
    }
 
    return 0;
}

Output:

Free 30-Day C Certification Bootcamp is Live. Join Now!
Running... Press Ctrl+C to test signal handling
Running... Press Ctrl+C to test signal handling
^C
Signal received: 2
Sanfoundry: Handling Ctrl+C gracefully!
Running... Press Ctrl+C to test signal handling

This program shows how to catch the Ctrl+C signal in C. It uses a function called sanfoundryHandler() to handle the signal. When Ctrl+C is pressed, the program doesn’t stop right away. Instead, it prints a custom message. The signal() function links SIGINT (Ctrl+C) to the handler. The program keeps running in a loop, printing a message every 2 seconds.

Sending Signals Programmatically

1. Using raise()

#include <stdio.h>
#include <signal.h>
 
void result_handler(int sig) {
    printf("Sanfoundry: raise() handled signal %d successfully!\n", sig);
}
 
int main() {
    signal(SIGUSR1, result_handler);
    raise(SIGUSR1);
    return 0;
}

Output:

Sanfoundry: raise() handled signal 10 successfully!

This program shows how to send and handle a signal in C. It sets a function result_handler() to run when SIGUSR1 is received. The signal() function connects the signal to the handler. The raise() function then sends SIGUSR1 to the program itself. When the signal is sent, the handler prints a message.

2. Using kill()

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
void terminate_handler(int sig) {
    printf("Sanfoundry: kill() handled signal %d\n", sig);
}
 
int main() {
    signal(SIGTERM, terminate_handler);
    kill(getpid(), SIGTERM); // Send SIGTERM to current process
    return 0;
}

Output:

advertisement
Sanfoundry: kill() handled signal 15

This C program sets up a custom handler for the SIGTERM signal. When the program sends this signal to itself using kill(), the handler prints a message instead of terminating the process. This shows how to catch and handle signals in C.

Blocking and Unblocking Signals with sigprocmask()

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
void pause_handler(int sig) {
    printf("Sanfoundry: Signal %d received during blocked state.\n", sig);
}
 
int main() {
    struct sigaction block_action;
    sigset_t signal_set, old_set;
 
    block_action.sa_handler = pause_handler;
    sigemptyset(&block_action.sa_mask);
    block_action.sa_flags = 0;
    sigaction(SIGINT, &block_action, NULL);
 
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGINT);
    sigprocmask(SIG_BLOCK, &signal_set, &old_set);  // Block SIGINT
 
    printf("Sanfoundry: SIGINT blocked for 5 seconds. Press Ctrl+C now.\n");
    sleep(5);
 
    printf("Sanfoundry: Unblocking SIGINT...\n");
    sigprocmask(SIG_SETMASK, &old_set, NULL);  // Unblock
 
    sleep(5);
    return 0;
}

Sample Output:

Sanfoundry: SIGINT blocked for 5 seconds. Press Ctrl+C now.
Sanfoundry: Unblocking SIGINT...
^C
Sanfoundry: Signal 2 received during blocked state.

This C program blocks SIGINT for 5 seconds. During this time, pressing Ctrl+C won’t trigger the signal handler. After 5 seconds, the signal is unblocked, and the handler processes it. This demonstrates signal blocking and unblocking.

Ignoring Signals Using SIG_IGN

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
int main() {
    signal(SIGINT, SIG_IGN);  // Ignore Ctrl+C
    printf("Sanfoundry: SIGINT is now being ignored. Try pressing Ctrl+C\n");
    sleep(10);
    printf("Sanfoundry: Program finished with SIGINT ignored.\n");
    return 0;
}

Sample Output (you press Ctrl+C, but nothing happens):

Sanfoundry: SIGINT is now being ignored. Try pressing Ctrl+C
Sanfoundry: Program finished with SIGINT ignored.

This C program ignores the SIGINT signal (triggered by Ctrl+C). It uses signal(SIGINT, SIG_IGN) to tell the program to ignore the signal. The program then waits for 10 seconds before finishing, during which pressing Ctrl+C has no effect.

Handling Multiple Signals

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
void sanfoundry_handler(int sig) {
    if (sig == SIGINT)
        printf("Sanfoundry: Caught SIGINT (Ctrl+C)\n");
    else if (sig == SIGTERM)
        printf("Sanfoundry: Caught SIGTERM (kill)\n");
}
 
int main() {
    signal(SIGINT, sanfoundry_handler);
    signal(SIGTERM, sanfoundry_handler);
 
    printf("Sanfoundry: Send SIGINT (Ctrl+C) or SIGTERM (kill)\n");
    while (1)
        sleep(1);
    return 0;
}

Sample Output:

Sanfoundry: Send SIGINT (Ctrl+C) or SIGTERM (kill)
^C
Sanfoundry: Caught SIGINT (Ctrl+C)

This C program handles SIGINT (Ctrl+C) and SIGTERM (sent by kill). The sanfoundry_handler function checks which signal is received and prints the corresponding message. The program runs in an infinite loop, waiting for and responding to signals.

Using sigaction() for Advanced Signal Handling

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
 
void certification_handler(int quiz_signal) {
    printf("Sanfoundry: Signal %d caught using sigaction!\n", quiz_signal);
}
 
int main() {
    struct sigaction quiz_action;
    quiz_action.sa_handler = certification_handler;
    sigemptyset(&quiz_action.sa_mask);
    quiz_action.sa_flags = 0;
 
    sigaction(SIGINT, &quiz_action, NULL);  // Handle Ctrl+C
 
    printf("Sanfoundry: Press Ctrl+C to send SIGINT...\n");
    while (1)
        sleep(1);
    return 0;
}

Sample Output (after pressing Ctrl+C):

Sanfoundry: Press Ctrl+C to send SIGINT...
^C
Sanfoundry: Signal 2 caught using sigaction!

This C program handles the SIGINT signal (Ctrl+C) using sigaction(). It sets up a custom handler, certification_handler, which prints a message when SIGINT is caught. The program runs in an infinite loop, waiting for Ctrl+C to trigger the handler.

Sanfoundry Global Education & Learning Series – 1000 C Tutorials.

If you wish to look at all C Tutorials, go to C Tutorials.

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.