开发者

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

开发者 https://www.devze.com 2022-12-22 05:34 出处:网络
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 handl

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 si开发者_高级运维gnal handling.


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).


The easiest way is to log via a (named) pipe (writes upto PIPE_MAX are atomic) , or via an UDP socket (idem). The message origin can be set by the function generating the message. Of course you'll need a process that actually reads and processes the messages, but it can be kept outside the context of a signal handler.


BTW: you don't need a separate process to recieve the messages, you can send the messages to your own process and add (the reading end of) the pipe to the fd_set (given your program sits in a select or poll loop), or poll it periodically.


Does your system have sigpending? I don't know what the behavior of that function is during a signal handler. If it returns a set flag, though, you could be pessimistic and skip async-unsafe calls if any signals are pending.

0

精彩评论

暂无评论...
验证码 换一张
取 消