Iterating over a list of possible signals

后端 未结 2 1945
情歌与酒
情歌与酒 2021-01-22 03:10

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

相关标签:
2条回答
  • 2021-01-22 03:28

    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
    
    0 讨论(0)
  • 2021-01-22 03:32

    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.

    0 讨论(0)
提交回复
热议问题