I have some code that I want to use to print a list of signals that prints the names of the signals in the signal mask of the calling process.
The starting code that I h
If you're looking for a list or array of signals, then I'm afraid that there isn't one defined in signal.h
. The only thing you can do is define it yourself and iterate over it. If you want, you could define it in a different helper file so as not to pollute the actual code.
Example program:
#include "siglist.h"
#include <stdio.h>
#include <stddef.h>
int main(void) {
sigset_t sigset;
// ... initialize stuff ...
for (size_t i = 0; i < SIGLIST_LENGTH; i++) {
if (sigismember(&sigset, siglist[i].code))
printf("%d - %s: %s.\n", siglist[i].code, siglist[i].name, siglist[i].description);
}
return 0;
}
File siglist.h
(all those ifdef
are needed since you cannot know beforehand which signals are defined and which aren't on the target machine):
#ifndef SIGLIST_H_INCLUDED
#define SIGLIST_H_INCLUDED
#include <signal.h>
struct siginfo {
int code;
char *name;
char *description;
};
const struct siginfo siglist[] = {
#ifdef SIGABRT
{SIGABRT , "SIGABRT" , "Abort signal"},
#endif
#ifdef SIGALRM
{SIGALRM , "SIGALRM" , "Timer signal"},
#endif
#ifdef SIGBUS
{SIGBUS , "SIGBUS" , "Bus error (bad memory access)"},
#endif
#ifdef SIGCHLD
{SIGCHLD , "SIGCHLD" , "Child stopped or terminated"},
#endif
#ifdef SIGCLD
{SIGCLD , "SIGCLD" , "Child stopped or terminated"},
#endif
#ifdef SIGCONT
{SIGCONT , "SIGCONT" , "Continue if stopped"},
#endif
#ifdef SIGEMT
{SIGEMT , "SIGEMT" , "Emulator trap"},
#endif
#ifdef SIGFPE
{SIGFPE , "SIGFPE" , "Floating-point exception"},
#endif
#ifdef SIGHUP
{SIGHUP , "SIGHUP" , "Hangup detected on controlling terminal or death of controlling process"},
#endif
#ifdef SIGILL
{SIGILL , "SIGILL" , "Illegal Instruction"},
#endif
#ifdef SIGINFO
{SIGINFO , "SIGINFO" , "Power failure"},
#endif
#ifdef SIGINT
{SIGINT , "SIGINT" , "Interrupt from keyboard"},
#endif
#ifdef SIGIO
{SIGIO , "SIGIO" , "I/O now possible"},
#endif
#ifdef SIGIOT
{SIGIOT , "SIGIOT" , "IOT trap: Abort signal"},
#endif
#ifdef SIGKILL
{SIGKILL , "SIGKILL" , "Kill signal"},
#endif
#ifdef SIGLOST
{SIGLOST , "SIGLOST" , "File lock lost "},
#endif
#ifdef SIGPIPE
{SIGPIPE , "SIGPIPE" , "Broken pipe: write to pipe with no readers"},
#endif
#ifdef SIGPOLL
{SIGPOLL , "SIGPOLL" , "Pollable event: I/O now possible"},
#endif
#ifdef SIGPROF
{SIGPROF , "SIGPROF" , "Profiling timer expired"},
#endif
#ifdef SIGPWR
{SIGPWR , "SIGPWR" , "Power failure"},
#endif
#ifdef SIGQUIT
{SIGQUIT , "SIGQUIT" , "Quit from keyboard"},
#endif
#ifdef SIGSEGV
{SIGSEGV , "SIGSEGV" , "Invalid memory reference"},
#endif
#ifdef SIGSTKFLT
{SIGSTKFLT, "SIGSTKFLT", "Stack fault on coprocessor"},
#endif
#ifdef SIGSTOP
{SIGSTOP , "SIGSTOP" , "Stop process"},
#endif
#ifdef SIGTSTP
{SIGTSTP , "SIGTSTP" , "Stop typed at terminal"},
#endif
#ifdef SIGSYS
{SIGSYS , "SIGSYS" , "Bad system call "},
#endif
#ifdef SIGTERM
{SIGTERM , "SIGTERM" , "Termination signal"},
#endif
#ifdef SIGTRAP
{SIGTRAP , "SIGTRAP" , "Trace/breakpoint trap"},
#endif
#ifdef SIGTTIN
{SIGTTIN , "SIGTTIN" , "Terminal input for background process"},
#endif
#ifdef SIGTTOU
{SIGTTOU , "SIGTTOU" , "Terminal output for background process"},
#endif
#ifdef SIGUNUSED
{SIGUNUSED, "SIGUNUSED", "Bad system call "},
#endif
#ifdef SIGURG
{SIGURG , "SIGURG" , "Urgent condition on socket "},
#endif
#ifdef SIGUSR1
{SIGUSR1 , "SIGUSR1" , "User-defined signal 1"},
#endif
#ifdef SIGUSR2
{SIGUSR2 , "SIGUSR2" , "User-defined signal 2"},
#endif
#ifdef SIGVTALRM
{SIGVTALRM, "SIGVTALRM", "Virtual alarm clock "},
#endif
#ifdef SIGXCPU
{SIGXCPU , "SIGXCPU" , "CPU time limit exceeded "},
#endif
#ifdef SIGXFSZ
{SIGXFSZ , "SIGXFSZ" , "File size limit exceeded"},
#endif
#ifdef SIGWINCH
{SIGWINCH , "SIGWINCH" , "Window resize signal"},
#endif
};
const size_t SIGLIST_LENGTH = sizeof(siglist)/sizeof(siglist[0]);
#endif // SIGLIST_H_INCLUDED
Create a structure type, and preload an array with the appropriate information:
struct SigInfo
{
int signum;
char signame[16];
};
static const struct SigInfo siginfo[] =
{
#ifdef SIGINT
{ SIGINT, "SIGINT" },
#endif
#ifdef SIGQUIT
{ SIGQUIT, "SIGQUIT" },
#endif
…
};
enum { NUM_SIGINFO = sizeof(siginfo) / sizeof(siginfo[0]) };
And then:
printf("%s", str);
for (int i = 0; i < NUM_SIGINFO; i++)
{
if (sigismember(&sigset, siginfo[i].signum))
{
printf(" %s\n", siginfo[i].signame);
break;
}
}
You can package the information multiple different ways. Generating the signal information is fiddly. I use a Perl script to scrutinize the appropriate header (usually /usr/include/sys/errno.h
) and extract the information shown, plus the text of what the signal is for, plus the number associated with the signal:
typedef struct sig_info
{
const char *sigsym; /* Signal symbol - "EINTR" */
int signum; /* Signal number - EINTR */
int sigdef; /* Signal define - 2 */
const char *sigmsg; /* Signal message - Interrupted system call */
} sig_info;
…
#ifdef SIGPIPE
{ "SIGPIPE", SIGPIPE, 13, "Broken pipe (POSIX)." },
#endif
#ifdef SIGPROF
{ "SIGPROF", SIGPROF, 27, "Profiling alarm clock (4.2 BSD)." },
#endif
#ifdef SIGPWR
{ "SIGPWR", SIGPWR, 30, "Power failure restart (System V)." },
#endif
…
The program this comes from allows me to find signals by name or number:
$ ./signal int 2
SIGINT (2): Interrupt (ANSI).
2 (SIGINT): Interrupt (ANSI).
$ ./signal -h
Usage: signal [-hlqV] [lo[:hi] ...]
-h Print help and exit
-l Print list of all signals
-q Validate signal but don't print messages
-V Print version and exit
$ ./signal -l
1 (SIGHUP): Hangup (POSIX).
2 (SIGINT): Interrupt (ANSI).
3 (SIGQUIT): Quit (POSIX).
4 (SIGILL): Illegal instruction (ANSI).
5 (SIGTRAP): Trace trap (POSIX).
6 (SIGIOT): IOT trap (4.2 BSD).
6 (SIGIOT): IOT trap (4.2 BSD).
7 (SIGBUS): BUS error (4.2 BSD).
8 (SIGFPE): Floating-point exception (ANSI).
9 (SIGKILL): Kill, unblockable (POSIX).
10 (SIGUSR1): User-defined signal 1 (POSIX).
11 (SIGSEGV): Segmentation violation (ANSI).
12 (SIGUSR2): User-defined signal 2 (POSIX).
13 (SIGPIPE): Broken pipe (POSIX).
14 (SIGALRM): Alarm clock (POSIX).
15 (SIGTERM): Termination (ANSI).
16 (SIGSTKFLT): Stack fault.
17 (SIGCHLD): Child status has changed (POSIX).
18 (SIGCONT): Continue (POSIX).
19 (SIGSTOP): Stop, unblockable (POSIX).
20 (SIGTSTP): Keyboard stop (POSIX).
21 (SIGTTIN): Background read from tty (POSIX).
22 (SIGTTOU): Background write to tty (POSIX).
23 (SIGURG): Urgent condition on socket (4.2 BSD).
24 (SIGXCPU): CPU limit exceeded (4.2 BSD).
25 (SIGXFSZ): File size limit exceeded (4.2 BSD).
26 (SIGVTALRM): Virtual alarm clock (4.2 BSD).
27 (SIGPROF): Profiling alarm clock (4.2 BSD).
28 (SIGWINCH): Window size change (4.3 BSD, Sun).
29 (SIGIO): I/O now possible (4.2 BSD).
30 (SIGPWR): Power failure restart (System V).
31 (SIGSYS): Bad system call.
34 (SIGRT34): Real time signal 34 (SIGRTMIN)
35 (SIGRT35): Real time signal 35
…
63 (SIGRT63): Real time signal 63
64 (SIGRT64): Real time signal 64 (SIGRTMAX)
$
This particular list of signals was generated on an ancient RedHat Linux machine (5.2, IIRC). The effect is similar on macOS, and other versions of Linux too.