Search code examples
csignalssignal-handlingasync-safe

Is there a way to test whether I'm in a signal handler?


I'm having to work on a logging module that can be called from various places in a large project. The problem I have is that sometimes the module may be called from code executed inside a signal handler. Normally, the logging module includes time data using localtime() and strftime(), but of course these calls are not async-signal safe, and can cause deadlocks if called from within a signal handler. Is there any way (on a GNU/Linux system) to tell whether or not my code is currently executing in a signal handler context, apart from e.g., having every signal handler set a flag while processing? I think it would be better to simplify our signal handlers, but in this case I don't have a choice as to where the logging module might be called. It would be nice if I could test and just omit the timestamp information if the module is called during signal handling.


Solution

  • First of all, your question ("Am I in a signal handler?") does not have a well-defined answer. Consider the following code:

    #include <setjmp.h>
    #include <signal.h>
    
    jmp_buf jb;
    int foo(int s)
    {
        longjmp(jb,1);
    }
    
    int main()
    {
        if (setjmp(jb)) {
            puts("Am I in a signal handler now, or not?");
            return 0;
        }
        signal(SIGINT, foo);
        raise(SIGINT);
    }
    

    With that said, there is a technique you could use to answer this question in a meaningful way for many programs. Choose a signal you don't intend to use, and add it to the sa_mask for all the signals you handle, installing the signal handlers using sigaction. Then you can use sigprocmask to check the current signal mask, and if your designated signal is in the signal mask, that means a signal handler has been invoked and has not yet returned (returning would restore the original signal mask).