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
