CPP Signal Handling

Understanding Signals in C++: Handling Program Interruptions

Signals play a crucial role in managing program execution interruptions. These interruptions, or signals, are dispatche

d to a process by the operating system and can lead to the abrupt termination of a program. For instance, you can generate a signal by pressing Ctrl+C on UNIX, Linux, macOS, or Windows systems. Signal handling in C++ involves using various functions and mechanisms to manage and respond to asynchronous events, such as interrupts or exceptions, that can interrupt the normal flow of program execution.

While some signals cannot be caught by a program, a predefined list of signals can be intercepted and managed in your code. These signals are enumerated in the C++ header file <csignal>.

Here is a list of signals that you can capture in your program and subsequently respond to based on the signal received:

Exploring Signal Types: Managing Program Interruptions

  1. SIGABRT: Signals abnormal program termination, typically invoked by a call to abort.
  2. SIGFPE: Indicates an erroneous arithmetic operation, like division by zero or overflow.
  3. SIGILL: Detects an illegal instruction within the program.
  4. SIGINT: Receives an interactive attention signal, often triggered by Ctrl+C.
  5. SIGSEGV: Points to an invalid memory access, often resulting in a segmentation fault.
  6. SIGTERM: Represents a termination request sent to the program.

Harnessing the signal() Function

The C++ signal-handling library provides the signal() function to capture unexpected events. Its syntax involves two arguments: an integer representing the signal number and a pointer to the signal-handling function. You must register the signal you want to catch using this function and link it to a signal handler. Here’s an example:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler(int signum) {
   cout << "Interrupt signal (" << signum << ") received.\n";

   // Perform necessary cleanup and terminate program
   exit(signum);  
}

int main () {
   // Register SIGINT signal and associate it with signalHandler  
   signal(SIGINT, signalHandler);  

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

   return 0;
}

Upon executing this code, you’ll observe that the program continues executing until you press Ctrl+C. Once you do, the program catches the SIGINT signal and responds accordingly:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

Using the raise() Function

The raise() function can be used to generate signals internally. It accepts a signal number as an argument and can trigger signals like SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, and SIGHUP. Here’s an example of using raise():

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler(int signum) {
   cout << "Interrupt signal (" << signum << ") received.\n";

   // Perform necessary cleanup and terminate program
   exit(signum);  
}

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

   while(++i) {
      cout << "Going to sleep...." << endl;
      if( i == 3 ) {
         raise(SIGINT);
      }
      sleep(1);
   }

   return 0;
}

Executing this code will automatically terminate the program after printing “Interrupt signal (2) received.” This demonstrates how raise() can trigger a signal internally.

In essence, signals are vital tools for managing program interruptions. By understanding signal types and leveraging functions like signal() and raise(), you can effectively handle these interruptions and ensure proper program termination or execution based on the received signal.


Discover more from PiEmbSysTech

Subscribe to get the latest posts sent to your email.

Leave a Reply

Scroll to Top

Discover more from PiEmbSysTech

Subscribe now to keep reading and get access to the full archive.

Continue reading