Ch20.3 – Pending Signals

 

Ch20.3 – Pending Signals
Linux System Programming Β· EmbeddedPathashala
πŸ“‘ Topic 3 of 19
🎯 Beginner–Intermediate
πŸ’» 2 Code Examples
❓ Interview Q&A
πŸ”‘ Key Terms
Pending Signal Signal Mask sigpending() Blocked Signal sigset_t /proc/PID/status SigPnd
What Does “Pending” Mean?

When the kernel generates a signal for a process but the process has that signal currently blocked (in its signal mask), the signal cannot be delivered yet. It stays in a waiting area called the pending signal set.

Think of it like a letter in a mailbox that you haven’t opened yet because you’re busy. The letter (signal) arrived (generated), but you haven’t read it (delivered) yet.

The pending state ends as soon as the process unblocks the signal β€” at that point the kernel delivers it immediately.

πŸ“¬ The Pending Signal Lifecycle
Step What Happens Signal State
1 Event occurs (e.g. timer expires) Generated
2 Signal is in the process’s signal mask (blocked) ⏳ Pending
3 Process removes signal from mask (unblocks it) Unblocked
4 Kernel delivers signal β€” handler runs or default action βœ… Delivered
Normal delivery (no blocking): If the signal is not blocked, steps 2 and 3 are skipped. The signal goes from Generated β†’ Delivered as soon as the process is scheduled.
πŸ“‚ Viewing Pending Signals via /proc

The kernel keeps per-process signal information in /proc/PID/status. The relevant fields are hex bitmasks where each bit represents a signal number:

Field in /proc/PID/status Meaning
SigPnd Per-thread pending signals
ShdPnd Process-wide pending signals (since kernel 2.6)
SigBlk Blocked (masked) signals
SigIgn Ignored signals
SigCgt Caught signals (have a handler installed)
Try it: While a process is sleeping, run cat /proc/<PID>/status | grep Sig to see these bitmasks.

πŸ’» Code Example 1 – Use sigpending() to Read Pending Signals

This program blocks SIGINT, then loops for 5 seconds while you can press Ctrl+C. During that time SIGINT becomes pending. We use sigpending() to check and print the pending set.

/* Example: Block SIGINT, check pending signals with sigpending()
   Compile: gcc -o pending_demo pending_demo.c
   Run:     ./pending_demo  then press Ctrl+C quickly */

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

int main(void)
{
    sigset_t block_set, pending_set;

    /* Step 1: block SIGINT */
    sigemptyset(&block_set);
    sigaddset(&block_set, SIGINT);
    sigprocmask(SIG_BLOCK, &block_set, NULL);

    printf("SIGINT is now blocked for 5 seconds.\n");
    printf("Press Ctrl+C β€” it will become PENDING.\n");

    sleep(5);   /* sleep while SIGINT may arrive */

    /* Step 2: check what is pending */
    sigpending(&pending_set);

    if (sigismember(&pending_set, SIGINT))
        printf("YES β€” SIGINT is currently PENDING!\n");
    else
        printf("No pending SIGINT detected.\n");

    /* Step 3: unblock β€” signal is delivered NOW */
    printf("Unblocking SIGINT β€” it will be delivered now...\n");
    sigprocmask(SIG_UNBLOCK, &block_set, NULL);

    /* If SIGINT was pending, process terminates here */
    printf("This line only prints if no SIGINT was pending.\n");

    return 0;
}
Expected: Press Ctrl+C within 5 seconds β†’ after sleep the program prints “SIGINT is PENDING”, then on unblock it terminates. If you don’t press Ctrl+C, no pending signal is found.

πŸ’» Code Example 2 – Read /proc/self/status to See SigPnd

This program blocks SIGINT, then reads its own /proc/self/status to show the SigPnd bitmask before and after pressing Ctrl+C.

/* Example: Read SigPnd from /proc/self/status
   Compile: gcc -o proc_sig proc_sig.c
   Run:     ./proc_sig then press Ctrl+C when prompted */

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

/* Helper: print SigPnd line from /proc/self/status */
void print_sig_status(void)
{
    FILE *f = fopen("/proc/self/status", "r");
    if (!f) { perror("fopen"); return; }

    char line[256];
    while (fgets(line, sizeof(line), f)) {
        /* Print only lines starting with Sig */
        if (strncmp(line, "Sig", 3) == 0)
            printf("  %s", line);
    }
    fclose(f);
}

int main(void)
{
    sigset_t block_set;

    /* Block SIGINT */
    sigemptyset(&block_set);
    sigaddset(&block_set, SIGINT);
    sigprocmask(SIG_BLOCK, &block_set, NULL);

    printf("=== Signal status BEFORE pressing Ctrl+C ===\n");
    print_sig_status();

    printf("\nNow press Ctrl+C within 5 seconds...\n");
    sleep(5);

    printf("\n=== Signal status AFTER pressing Ctrl+C ===\n");
    print_sig_status();

    /* Unblock to deliver */
    sigprocmask(SIG_UNBLOCK, &block_set, NULL);

    return 0;
}
Look at SigPnd: Before Ctrl+C it will be 0000000000000000. After, you’ll see a non-zero hex value with bit 1 set (SIGINT = signal 2, so second bit from the right).

❓ Interview Questions
Q1. What is a pending signal?
A pending signal is one that has been generated but not yet delivered to the process. This happens when the signal is currently blocked by the process’s signal mask. It waits in the kernel until the signal is unblocked.
Q2. How do you check which signals are pending for a process?
Using the sigpending() system call, which fills a sigset_t with the set of currently pending signals. Alternatively, you can read /proc/PID/status and look at the SigPnd field (a hex bitmask).
Q3. When exactly is a pending signal delivered?
A pending signal is delivered as soon as it is unblocked (removed from the signal mask). SUSv3 guarantees that at least one pending signal is delivered before the sigprocmask() unblocking call returns.
Q4. What does the SigPnd field in /proc/PID/status show?
It is a hexadecimal bitmask where each bit represents a signal number. If bit N is set, signal N is currently pending for that thread. The least significant bit is signal 1.
Q5. Can you change the disposition of a pending signal before it is delivered?
Yes. If you change a pending signal’s disposition to SIG_IGN before unblocking it, the signal is removed from the pending set and never delivered. This is a way to discard pending signals.
Next Topic β†’

Signal Mask & Blocking – How does a process block signals from being delivered?

Next: Signal Mask & Blocking β†’ ← Previous

Leave a Reply

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