Ch20.13 โ€“ Signal Sets (sigset_t)

 

Ch20.13 โ€“ Signal Sets (sigset_t)
Linux System Programming ยท EmbeddedPathashala
๐Ÿ“ก Topic 13 of 19
๐ŸŽฏ Intermediate
๐Ÿ’ป 3 Code Examples
โ“ Interview Q&A
๐Ÿ”‘ Key Terms
sigset_t sigemptyset() sigfillset() sigaddset() sigdelset() sigismember() sigandset() sigorset() sigisemptyset()
What is a Signal Set?

Many system calls (sigprocmask, sigpending, sigaction) need to work with a group of signals at once. The data type used for this is sigset_t โ€” a bitmask where each bit represents one signal.

On Linux, sigset_t is implemented as a bitmask, but the POSIX standard only requires it to be an assignable type. Never use memset or direct bit manipulation โ€” always use the provided API functions.

๐Ÿ“‹ Signal Set API Summary
Function Action
sigemptyset(&set) Initialize set to contain NO signals
sigfillset(&set) Initialize set to contain ALL signals
sigaddset(&set, sig) Add signal sig to set
sigdelset(&set, sig) Remove signal sig from set
sigismember(&set, sig) Returns 1 if sig is in set, 0 if not
sigandset(&dst, &l, &r) dst = intersection of l and r (Linux-specific)
sigorset(&dst, &l, &r) dst = union of l and r (Linux-specific)
sigisemptyset(&set) Returns 1 if set contains no signals (Linux-specific)
Always initialise: Before using a sigset_t variable, call sigemptyset() or sigfillset(). C does not zero-initialise automatic (stack) variables, so an uninitialized sigset_t has unpredictable content.
๐Ÿ’ป Code Example 1 โ€“ Build and Inspect a Signal Set
/* Build a signal set and query membership
   Compile: gcc -o sigset_demo sigset_demo.c
   Run: ./sigset_demo */

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

int main(void)
{
    sigset_t my_set;

    /* MUST initialise first */
    sigemptyset(&my_set);

    /* Add some signals */
    sigaddset(&my_set, SIGINT);
    sigaddset(&my_set, SIGTERM);
    sigaddset(&my_set, SIGUSR1);

    /* Test membership */
    printf("SIGINT  in set? %s\n", sigismember(&my_set, SIGINT)  ? "YES":"NO");
    printf("SIGTERM in set? %s\n", sigismember(&my_set, SIGTERM) ? "YES":"NO");
    printf("SIGUSR2 in set? %s\n", sigismember(&my_set, SIGUSR2) ? "YES":"NO");

    /* Remove SIGTERM */
    sigdelset(&my_set, SIGTERM);
    printf("After remove: SIGTERM in set? %s\n",
           sigismember(&my_set, SIGTERM) ? "YES":"NO");

    return 0;
}
๐Ÿ’ป Code Example 2 โ€“ Print All Members of a Signal Set
/* Print all signals present in a sigset_t
   Compile: gcc -D_GNU_SOURCE -o print_set print_set.c */

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

void printSigSet(const sigset_t *set)
{
    int sig, found = 0;
    for (sig = 1; sig < NSIG; sig++) {
        if (sigismember(set, sig)) {
            printf("  Signal %2d: %s\n", sig, strsignal(sig));
            found++;
        }
    }
    if (!found)
        printf("  (empty set)\n");
}

int main(void)
{
    sigset_t full, empty, custom;

    sigfillset(&full);
    sigemptyset(&empty);

    sigemptyset(&custom);
    sigaddset(&custom, SIGINT);
    sigaddset(&custom, SIGCHLD);
    sigaddset(&custom, SIGUSR1);

    printf("Full set (first 5 shown):\n");
    int s, n = 0;
    for (s = 1; s < NSIG && n < 5; s++)
        if (sigismember(&full, s)) {
            printf("  %d: %s\n", s, strsignal(s));
            n++;
        }

    printf("\nEmpty set:\n");
    printSigSet(&empty);

    printf("\nCustom set:\n");
    printSigSet(&custom);

    return 0;
}
๐Ÿ’ป Code Example 3 โ€“ sigandset() and sigorset() (Linux-specific)
/* Set operations: union and intersection
   Compile: gcc -D_GNU_SOURCE -o set_ops set_ops.c */

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

void printSigSet(const char *name, const sigset_t *set)
{
    printf("%s: ", name);
    int sig, found = 0;
    for (sig = 1; sig < NSIG; sig++)
        if (sigismember(set, sig)) { printf("%d ", sig); found++; }
    if (!found) printf("(empty)");
    printf("\n");
}

int main(void)
{
    sigset_t a, b, result;

    sigemptyset(&a);
    sigaddset(&a, SIGINT);   /* 2 */
    sigaddset(&a, SIGTERM);  /* 15 */

    sigemptyset(&b);
    sigaddset(&b, SIGTERM);  /* 15 */
    sigaddset(&b, SIGUSR1);  /* 10 */

    printSigSet("Set A", &a);
    printSigSet("Set B", &b);

    /* Union: A | B */
    sigorset(&result, &a, &b);
    printSigSet("Union (A|B)", &result);

    /* Intersection: A & B */
    sigandset(&result, &a, &b);
    printSigSet("Intersection (A&B)", &result);

    /* Check if set is empty */
    printf("Intersection empty? %s\n",
           sigisemptyset(&result) ? "YES" : "NO");

    return 0;
}
โ“ Interview Questions
Q1. What is sigset_t and why must it be initialized before use?
sigset_t is the data type representing a set of signals, implemented as a bitmask on Linux. It must be initialized with sigemptyset() or sigfillset() because automatic variables in C are not zero-initialized โ€” an uninitialized sigset_t has garbage content and unpredictable behaviour.
Q2. Why should you not use memset to zero a sigset_t?
POSIX does not require sigset_t to be a bitmask. On some implementations it could be a struct or use non-zero internal state for “empty.” Using memset is non-portable. Use sigemptyset() instead โ€” it is guaranteed to create a valid empty set.
Q3. What is the difference between sigemptyset() and sigfillset()?
sigemptyset() initializes the set to contain no signals. sigfillset() initializes the set to contain all signals (1 through NSIG-1, including realtime signals).
Q4. Which signal set functions are Linux-specific (not in POSIX)?
sigandset() (intersection), sigorset() (union), and sigisemptyset() (empty check) are Linux-specific GNU extensions. They require defining _GNU_SOURCE and are not portable to other UNIX systems.
Next Topic โ†’

sigprocmask() โ€” Full details on manipulating the process signal mask

Next: sigprocmask() โ†’ โ† Previous

Leave a Reply

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