Introduction

Signal Handling in C refers to the process of catching and responding to runtime events like division by zero, segmentation faults, or interrupts (e.g., pressing Ctrl+C). A signal acts as a notification that the operating system sends to a process, informing it that something significant has occurred — often requiring the program to respond or shut down safely.

Understanding Signal Handling in C helps developers build resilient software that can manage errors, clean up resources, and exit gracefully. Without proper handling, a C program might crash unexpectedly or leave memory leaks behind.

Why Study This Topic?

In real-world systems, unpredictable events often occur—like a user pressing Ctrl+C or a system issuing a segmentation fault. Handling these signals gracefully ensures the program terminates safely or recovers appropriately.

Real-time fun example:
Think of signal handling like a fire alarm in a school. When the alarm rings (signal), the ongoing class (program flow) is interrupted, and students follow a fire drill (handler function) to exit safely. Without this plan, chaos ensues!

What Will Be Covered?

  • What are signals in C
  • Common types of signals
  • Using signal() function
  • Using sigaction() for advanced handling
  • Creating custom signal handlers
  • Real-time examples and use cases
  • Best practices and safety tips

What Are Signals?

A signal is a notification sent to a process by the OS to notify it of events like division by zero, segmentation fault, or user interrupt.

Common Signals in C

SignalDescriptionConstant
InterruptCtrl+CSIGINT
TerminateKill from OSSIGTERM
SegmentationInvalid memory accessSIGSEGV
ArithmeticDivision by zero, etc.SIGFPE
AlarmTimer expiredSIGALRM

Handling Signals with signal() Function

You can use the signal() function to catch signals and run a specific handler function when a signal occurs.

Syntax

void (*signal(int signum, void (*handler)(int)))(int);
  • signum: The signal number (e.g., SIGINT)
  • handler: The function that handles the signal

Example: Handling Ctrl+C

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

void handler(int signum) {
    printf("Caught signal %d\n", signum);
}

int main() {
    signal(SIGINT, handler);
    while (1);  // Program waits indefinitely; press Ctrl+C to test
    return 0;
}

Explanation

  • The program runs until you press Ctrl+C.
  • When the OS sends SIGINT, the program runs the handler() function instead of exiting immediately.
  • This allows you to manage clean-up or give custom messages.

Limitations of signal()

  • On some systems, it resets the handler after catching a signal once.
  • It doesn’t allow signal blocking or detailed behavior control.

To gain more control, use sigaction().

Advanced Handling with sigaction()

The sigaction() function offers better control and safer signal handling.

Syntax

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  • signum: Signal to handle
  • act: Defines the new behavior
  • oldact: Optionally stores the previous behavior

Example: Handling SIGINT Safely

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

void handler(int signum) {
    printf("Handled signal %d safely.\n", signum);
}

int main() {
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = handler;

    sigaction(SIGINT, &act, NULL);

    while (1);  // Press Ctrl+C to see the custom message
    return 0;
}

Explanation

  • sigaction() installs the handler function for SIGINT.
  • memset() clears the sigaction struct before use.
  • The custom handler runs every time you press Ctrl+C, without resetting.

Ignoring or Restoring Signals

signal(SIGINT, SIG_IGN);   // Ignore Ctrl+C
signal(SIGINT, SIG_DFL);   // Restore default behavior

Best Practices

  • Keep handlers short and non-blocking.
  • Avoid using printf() in handlers; use write() instead.
  • Use sigaction() for reliability.
  • Reinstall handler if using signal() on older systems.
  • Do not perform memory allocation inside handlers.

Summary

  • Signals are software interrupts from the OS or user.
  • signal() is simple, but sigaction() is more robust.
  • You can catch, ignore, or restore signal behavior.
  • Proper signal handling prevents data corruption and allows graceful exits.

Learning Outcomes

After completing this topic, learners will:

  • Understand what signals are and how they function
  • Use signal() and sigaction() to create custom handlers
  • Identify and respond to various system-generated signals
  • Write safe and effective signal-handling code
  • Apply best practices for interrupt-driven programming

Common Interview Questions

Q1. What is signal handling in C?
A: It allows a program to handle asynchronous events like interrupts.
Asked in: Infosys, Capgemini


Q2. What’s the difference between signal() and sigaction()?
A: sigaction() provides more reliable and flexible signal handling.
Asked in: TCS, Cognizant


Q3. What happens when a signal is ignored?
A: The process continues its execution uninterrupted.
Asked in: Wipro, IBM


Q4. Can we assign custom functions to handle signals?
A: Yes, using signal() or sigaction().
Asked in: Zoho, Accenture


Q5. Is it safe to use printf() in a signal handler?
A: No, because it’s not async-signal-safe. Use write() instead.
Asked in: Tech Mahindra, HCL


Practice Exercises

Coding Challenge:

Write a C program that catches both SIGINT and SIGTERM using sigaction(). Log a message and exit cleanly.

Scenario

You’re building a file server in C. If a client suddenly disconnects or presses Ctrl+C during upload, your program shouldn’t crash. Instead, it should catch the interrupt signal, save logs, close open files, and exit gracefully—exactly what proper signal handling ensures.

Now Paly Time :

Additional Resources

  • GNU C Signal Handling Guide
  • Book: Advanced C Programming by Peter van der Linden
  • Tool: Signal Explorer (Online Linux sandbox for testing signals)

Leave a Reply

Your email address will not be published. Required fields are marked *