What is a Signal?


Signals are interrupts delivered to a process by the operating system, which can potentially terminate our program prematurely. For example, pressing "Ctrl+C" on various operating systems such as Linux, UNIX, Mac OS X, or Windows generates an interrupt. Signals come in various types; some can be caught by the program, while others cannot.

Below is a list of catchable signals in a program and the corresponding actions that can be taken based on each signal. To handle signals in C++, we need to include the <csignal>header file.

TYPESIGNALDESCRIPTION
Int (signals)SIGABRTSignal Abort - Abnormal termination, such as initiated by the abort function.
Int (signals)SIGFPESignal Floating-point Exception - An erroneous arithmetic operation, such as an overflow or divide by zero.
Int (signals)SIGILLSignal Illegal Instruction - Invalid function image, such as an illegal instruction, often due to code corruption or an attempt to execute data.
Int (signals)SIGINTSignal Interrupt - Interactive attention signal, usually generated by the application user.
Int (signals)SIGSEGVSignal Segmentation Violation - Invalid access to storage, like reading or writing outside the allocated memory.
Int (signals)SIGTERMSignal Terminate - A request sent to the program for termination.
Function (handlers)SIG_DFLDefault Handling - The signal is handled by the default action for that particular signal.
Function (handlers)SIG_IGNIgnore Signal - The signal is ignored.
Function (handlers)SIG_ERRSignal Error - A special return value indicating failure.

The signal()function is provided by the C++ signal-handling library to trap unexpected and unwanted events. Below is the general form of the signal()function:

void(*signal(intsig, void(*func)(int)))(int);

This function requires two arguments:

  • An integer specifying the signal number.
  • A pointer specifying the signal-handling function.

Here's a simple example where we catch an SIGINT(Interrupt Signal) using the signal()function. To catch a specific signal in our program, we must register it using the signal function and associate it with a signal handler.

SIGNAL() - C++ Copy to Clipboard  
#include <iostream>
#include <csignal> // Required for signal handling

using namespace std;

void signalHandler(int signum) {
   cout << "Interrupt signal (" << signum << ") received.\n";
   // Perform necessary cleanup here
   // Terminate the program
   exit(signum);
}

int main() {
   // Register the SIGINT signal and the signal handler
   signal(SIGINT, signalHandler);

   while (1) {
      cout << "Sleeping...." << endl;
      sleep(1);
   }

   return 0;
}

When we compile and execute our program, it works normally. If we press "Ctrl+C" to interrupt the execution, our program catches the signal and exits the loop.

We can generate signals using the raise()function. This function requires an argument, which is an integer signal number.

int raise(int sig);

Here, sigis the signal number to send, such as SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, or SIGHUP. Below is an example where we raise a signal internally using the raise()function:.

RAISE() - C++ CODE Copy to Clipboard  
#include <iostream>
#include <csignal> // Required for signal handling

using namespace std;

void signalHandler(int signum) {
   cout << "Interrupt signal (" << signum << ") received.\n";
   // Cleanup and close up stuff here
   // Terminate program
   exit(signum);
}

int main() {
   int i = 0;
   // Register signal SIGINT and signal handler
   signal(SIGINT, signalHandler);

   while (++i) {
      cout << "Sleeping...." << endl;

      if (i == 3) {
         raise(SIGINT);
      }

      sleep(1);
   }

   return 0;
}

In this example, the program raises the SIGINTsignal internally when iequals 3. The signal handler catches the signal and terminates the program accordingly.