Signals in C

Signals in C

Signals are a mechanism in Unix-like operating systems by which a process can be notified of, and act upon, specific conditions. In C, especially when working on Unix or Linux systems, signals provide a way to handle asynchronous events like interrupts. The C Standard Library provides functions to deal with signals.

1. Basics of Signals:

A signal can be generated due to various reasons like:

  • Division by zero.
  • Pressing certain key combinations (e.g., Ctrl+C sends SIGINT).
  • Other programs or processes can send signals.

2. Handling Signals:

The basic function to set a signal handler is:

#include <signal.h>

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

Here:

  • sig is the signal number.
  • func is a pointer to the function which will handle this signal.

3. Common Signals:

Here are some commonly encountered signals:

  • SIGINT: Interrupt signal, like when you press Ctrl+C.
  • SIGABRT: Abnormal termination.
  • SIGFPE: Erroneous arithmetic operations like division by zero.
  • SIGSEGV: Invalid memory reference.
  • SIGTERM: Termination request sent to the program.

4. Example of Signal Handling:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// Signal handler for SIGINT
void handle_sigint(int sig) {
    printf("Caught signal %d\n", sig);
}

int main() {
    // Connecting SIGINT to our handler
    signal(SIGINT, handle_sigint);
    
    // Infinite loop to keep our program running to demonstrate the signal handler
    while (1) {
        printf("Hello, World!\n");
        sleep(1);
    }

    return 0;
}

In this example, if you run the program and press Ctrl+C, instead of immediately terminating, the program will print "Caught signal 2" and continue running.

5. Default Signal Action:

Every signal has a default action associated with it, which might be:

  • Terminating the process.
  • Ignoring the signal.
  • Stopping the process.
  • etc.

You can revert to the default behavior of a signal by using:

signal(SIGINT, SIG_DFL);

6. Ignoring Signals:

You can set a signal to be ignored using:

signal(SIGINT, SIG_IGN);

However, not all signals can be ignored.

7. Caveats and Recommendations:

  1. Reentrancy: Signal handlers run asynchronously. Most of the C library functions are not "reentrant". It means they maintain internal states and calling them from signal handlers can be problematic. Thus, always be cautious about which functions you call inside a signal handler.

  2. sigaction() Over signal(): The signal() function behavior can vary across different systems. The sigaction() function is recommended for portable applications, as it provides more control over how the signal is delivered.

  3. Avoid Assumptions: Signal delivery timing is unpredictable. It's best not to make assumptions about the order or time when signals will be delivered.

  4. Masking and Blocking Signals: Advanced handling includes the ability to block certain signals from interrupting your process until they are unblocked.

8. Conclusion:

Signals in C provide a powerful mechanism to handle asynchronous events, but they come with complexities. Proper understanding and careful handling are essential to avoid pitfalls and make the most of signals.


More Tags

android-service virtualhost python-3.2 bundler mysql-error-1292 npm-scripts puzzle ngrok wkwebview android-phone-call

More Programming Guides

Other Guides

More Programming Examples