Signal handler for all signal
Asked Answered
S

2

5

How can I register a signal handler for ALL signal, available on the running OS, using signal(3)?

My code looks like this:

void sig_handler(int signum)
{
    printf("Received signal %d\n", signum);
}


int main()
{
    signal(ALL_SIGNALS_??, sig_handler);
    while (1) {
        sleep(1);
    };
    return 0;
}
Speak answered 22/6, 2013 at 22:7 Comment(9)
In for loop, from 1 to 31?Gid
Each system has a list of signals. See /usr/include/signal.h There is no single standard macro you can use to represent all of them. Plus. You cannot trap all of them, SIGKILL for example.Doralyn
Yes, I already mentioned that. But on some mordern OS are having more than 32. kill -l on FreeBSD for example returns 126 entries.Speak
Then you should check on which Platform you are... But I don't think you need them all, SIGINT, SIGUSR1/2 and a few more should be enough. btw. in /usr/include/bits/signum.h you find all with their description.Tal
okay I have to consider mac os x and freeBSD, I will just use a for loop that counts to the OS specific signal count. Thank you all for your help!!Speak
You cannot use printf() in a signal handler. (it is non-reentant)Selfpreservation
@wildplasser: Actually in this program it's perfectly valid to use printf in the signal handler. The restriction on using non-async-signal-safe functions in signal handlers only applies if the signal interrupts a non-AS-safe function. All the functions called from main in this program are AS-safe, so the signal handler can use any functions it wants. Of course this analysis only applies to the sample program in the question; it likely does not apply to OP's actual program.Labrie
@R and what happens if a signal arrives while the printf is being executed within the signal handler? (Hint: bad things) It is not safe to call printf in a signal handler, even in this simple program.Tenaille
Read carfully signal(7). Some signals (e.g. SIGKILL) cannot be caught.Profundity
L
7

Most systems have a macro NSIG or _NSIG (the former would not be available in standards-conformance mode since it violates the namespace) defined in signal.h such that a loop for (i=1; i<_NSIG; i++) will walk all signals. Also, on POSIX systems that have signal masks, CHAR_BIT*sizeof(sigset_t) is an upper bound on the number of signals which you could use as a fallback if neither NSIG nor _NSIG is defined.

Labrie answered 22/6, 2013 at 23:37 Comment(2)
source: 24.2 Standard Signals - The GNU C LibraryRademacher
But I don't understand why not i = 0 but i = 1. According to the explanation in the link above, the value of NSIG corresponds both to the number of signals defined and to <largest signal number> + 1, which implies that the signal number starts with 0. I suspect your code is intentional so could you give me an explanation? (Maybe What does kill -0 do? is related?)Rademacher
O
3

Signal handlers have to deal with reentrancy concerns and other problems. In practice, it's often more convenient to mask signals and then retrieve them from time to time. You can mask all signals (except SIGSTOP and SIGKILL, which you can't handle anyway) with this:

sigset_t all_signals;
sigfillset(&all_signals);
sigprocmask(SIG_BLOCK, &all_signals, NULL);

The code is slightly different if you're using pthreads. Call this in every thread, or (preferably) in the main thread before you create any others:

sigset_t all_signals;
sigfillset(&all_signals);
pthread_sigmask(SIG_BLOCK, &all_signals, NULL);

Once you've done that, you should periodically call sigtimedwait(2) like this:

struct timespec no_time = {0, 0};
siginfo_t result;
int rc = sigtimedwait(&all_signals, &result, &no_time);

If there is a signal pending, information about it will be placed in result and rc will be the signal number; if not, rc will be -1 and errno will be EAGAIN. If you're already calling select(2)/poll(2) (e.g. as part of some event-driven system), you may want to create a signalfd(2) instead and attach it to your event loop. In this case, you still need to mask the signals as shown above.

Orpine answered 14/11, 2014 at 15:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.