Signal Handling in C++

Last Updated : 18 Jul, 2026

Signals are notifications sent by the operating system to a process when specific events occur, such as user interrupts, invalid operations, or termination requests. C++ provides signal handling through the <csignal> header, allowing programs to define custom handlers for these events.

  • Detects runtime events generated by the operating system.
  • Allows custom handling instead of the default behavior.

Example: The following program runs continuously. Pressing Ctrl + C generates the SIGINT signal, which terminates the program.

C++
#include <iostream>
using namespace std;

int main() {

    while(1){
        cout << "GFG!\n";
    }
    return 0;
}

Explanation

  • The program continuously prints "GFG".
  • Pressing Ctrl + C sends the SIGINT signal.
  • Since no signal handler is registered, the program terminates.

Syntax

Every signal has a default behavior, but C++ allows programs to replace it with a custom signal handler using the signal() function.

signal(signal_type, signal_handler);

Where:

  • signal_type specifies the signal to handle.
  • signal_handler is the function executed when the signal occurs.

Common Signals in C++

The following are some commonly used signals available in C++ and POSIX systems.

SignalDescriptionDefault Behavior
SIGABRTAbnormal termination using abort()Terminates the program
SIGFPEArithmetic error (divide by zero, overflow)Terminates the program
SIGILLIllegal machine instructionTerminates the program
SIGINTUser interrupt (Ctrl + C)Terminates the program
SIGSEGVInvalid memory accessTerminates the program
SIGTERMProgram termination requestTerminates the program
SIGKILLForcefully kills a processCannot be caught or ignored
SIGQUITQuit signalTerminates and creates a core dump
SIGCHLDChild process status changedIgnored by default
SIGSTOPStops a processCannot be caught or ignored
SIGSYSInvalid system callTerminates the program
SIGUSR1User-defined signalCan be handled by the program

Note: Some signals, such as SIGKILL and SIGSTOP, cannot be caught, blocked, or ignored.

Example: Handling SIGINT

C++
#include <csignal>
#include <iostream>
using namespace std;

// Signal handler function
void signalHandler(int sig) {
    cout << "Interrupt handle " << sig << endl;
    
    // Optionally exit the program after handling
    exit(sig);
}

int main() {
    
    // Handle signal
    signal(SIGINT, signalHandler);

    // Loop that waits for the signal
    while (true) {
        cout << "Geeks\n";
    }
    return 0;
}


Output

Geeks
Geeks
Geeks
....
Ctrl+C (Enter by user)
Interrupt handle 2

Explanation

  • signal() registers signalHandler() for the SIGINT signal.
  • When Ctrl + C is pressed, the operating system generates SIGINT.
  • Instead of terminating immediately, the registered handler executes first.

Raising Signals Programmatically

Signals can also be generated manually from within a program.

1. Using raise()

The raise() function sends a signal to the current process.

Syntax

raise(signal_type);

It returns:

  • 0 on success.
  • A non-zero value if the signal could not be raised.
C++
#include <csignal>
#include <iostream>
using namespace std;

void signalHandler(int sig) {
    cout << "Signal received: " << sig << endl;
}

int main() {

    signal(SIGINT, signalHandler);

    raise(SIGINT);

    return 0;
}

Output
Signal received: 2

Explanation

  • raise(SIGINT) generates the interrupt signal for the current process.
  • Since a handler is registered, it executes immediately.

2. Using kill()

The kill() function sends a signal to another process or to the current process using its process ID.

Note: kill() is available only on POSIX-compliant operating systems such as Linux and macOS.

Syntax

kill(process_id, signal_type);

Where:

  • process_id specifies the target process.
  • signal_type specifies the signal to send.
C++
#include <csignal>
#include <iostream>
#include <unistd.h>
using namespace std;

void signalHandler(int sig) {
    cout << "Signal received: " << sig << endl;
}

int main() {

    signal(SIGINT, signalHandler);

    pid_t pid = getpid();

    kill(pid, SIGINT);

    return 0;
}

Output
Signal received: 2

Explanation

  • getpid() obtains the current process ID.
  • kill(pid, SIGINT) sends SIGINT to that process.
  • The registered signal handler executes.

Applications of Signal Handling

Signal handling is commonly used in the following situations:

  • Gracefully terminating programs before exit.
  • Cleaning up allocated resources.
  • Responding to keyboard interrupts.
  • Implementing user-defined notifications between processes.

Limitations of Signal Handling

Although useful, signal handling has several limitations:

  • Some signals (SIGKILL, SIGSTOP) cannot be handled.
  • Only async-signal-safe operations should be performed inside signal handlers.
  • Signal behavior may differ across operating systems.
  • Complex logic inside handlers can lead to unpredictable behavior.

Best Practices

Follow these practices while working with signals:

  • Keep signal handlers short and simple.
  • Avoid performing memory allocation or I/O-intensive operations inside handlers.
  • Use signals mainly for notifications rather than normal program flow.
  • Release resources safely before terminating the program.
Comment