A signal that has been generated (sent to the process) but not yet delivered (acted upon) is called a pending signal. This happens when the signal is currently in the process’s signal mask (blocked).
sigpending() returns the set of signals that are currently pending for the calling process, allowing you to inspect what is waiting to be delivered before you unblock those signals.
#include <signal.h>
int sigpending(sigset_t *set);
/* Returns 0 on success, or -1 on error */
On success, the sigset_t pointed to by set is filled with the set of signals currently pending for the calling process. Use sigismember() to check for individual signals.
| Stage | Description | sigpending() shows it? |
|---|---|---|
| Generated | Signal sent via kill(), hardware fault, etc. | Only if currently blocked |
| Pending | Signal is in the mask β waiting to be delivered | β YES |
| Delivered | Mask removed β signal is handled/ignored/default | β NO (no longer pending) |
/* Demonstrate sigpending() after blocking and sending a signal
Compile: gcc -o pending_demo pending_demo.c
Run: ./pending_demo */
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(void)
{
sigset_t block_set, old_set, pending;
/* Block SIGUSR1 */
sigemptyset(&block_set);
sigaddset(&block_set, SIGUSR1);
sigprocmask(SIG_BLOCK, &block_set, &old_set);
/* Send SIGUSR1 to ourselves β it will become pending */
kill(getpid(), SIGUSR1);
/* Now check what is pending */
sigpending(&pending);
if (sigismember(&pending, SIGUSR1))
printf("SIGUSR1 is PENDING (blocked, not yet delivered)\n");
else
printf("SIGUSR1 is NOT pending\n");
/* Restore old mask β SIGUSR1 will be delivered now */
printf("Restoring mask β SIGUSR1 will be delivered next...\n");
sigprocmask(SIG_SETMASK, &old_set, NULL);
/* Default action for SIGUSR1 is termination β program ends here */
printf("This line won't print unless SIGUSR1 is caught.\n");
return 0;
}
/* Print names of all currently pending signals
Compile: gcc -o show_pending show_pending.c
Run: ./show_pending */
#include <stdio.h>
#include <signal.h>
#include <string.h>
void print_pending(void)
{
sigset_t pending;
int sig;
if (sigpending(&pending) == -1) {
perror("sigpending");
return;
}
printf("Pending signals:\n");
int found = 0;
for (sig = 1; sig < NSIG; sig++) {
if (sigismember(&pending, sig)) {
printf(" [%2d] %s\n", sig, strsignal(sig));
found = 1;
}
}
if (!found)
printf(" (none)\n");
}
int main(void)
{
sigset_t block_all, old;
/* Block everything so we can inspect */
sigfillset(&block_all);
sigprocmask(SIG_BLOCK, &block_all, &old);
/* Send several signals to ourselves */
kill(getpid(), SIGUSR1);
kill(getpid(), SIGUSR2);
kill(getpid(), SIGTERM);
print_pending();
/* Restore β signals delivered, process likely terminated */
sigprocmask(SIG_SETMASK, &old, NULL);
return 0;
}
/* Change disposition of a pending signal to SIG_IGN to discard it
When a pending signal's disposition is set to SIG_IGN, it is
removed from the pending set and never delivered. */
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(void)
{
sigset_t block_set, old_set, pending;
/* Block SIGTERM */
sigemptyset(&block_set);
sigaddset(&block_set, SIGTERM);
sigprocmask(SIG_BLOCK, &block_set, &old_set);
/* Send SIGTERM to ourselves */
kill(getpid(), SIGTERM);
sigpending(&pending);
printf("SIGTERM pending: %s\n",
sigismember(&pending, SIGTERM) ? "YES" : "NO");
/* Ignore SIGTERM β this discards the pending instance */
signal(SIGTERM, SIG_IGN);
sigpending(&pending);
printf("After SIG_IGN, SIGTERM pending: %s\n",
sigismember(&pending, SIGTERM) ? "YES" : "NO");
/* Restore mask β nothing to deliver now */
sigprocmask(SIG_SETMASK, &old_set, NULL);
printf("Unblocked. SIGTERM was discarded.\n");
return 0;
}
SIG_IGN while it is still blocked, the pending signal is silently discarded β it will never be delivered even after unblocking.You can inspect pending signals for any process via the filesystem:
cat /proc/$(pidof myprogram)/status | grep Sig
# SigPnd: 0000000000000200 β per-thread pending
# ShdPnd: 0000000000000000 β process-wide pending (Linux 2.6+)
# SigBlk: 0000000000000200
# SigIgn: 0000000000000000
# SigCgt: 0000000000000000
The hex value is a bitmask. Bit 1 = signal 1, bit 2 = signal 2, etc. Value 0x200 = bit 9 = SIGKILL… actually signal 10 (SIGUSR1) in this example.
python3 -c "mask=0x200; [print(i) for i in range(1,32) if mask & (1<<(i-1))]"/proc/PID/status and look at the SigPnd (per-thread) and ShdPnd (process-wide) fields. They are hex bitmasks β bit N-1 being set means signal N is pending.SigPnd shows signals pending for a specific thread, while ShdPnd (added in Linux 2.6) shows signals pending for the entire process (sent via kill() to the process group rather than a specific thread). In a single-threaded process, both typically show the same information.