Search code examples
csignalsrace-conditionposix-select

How to ensure that signal handler finished and only then continue program?


I have SIGINT handler. It sets variable for whole program: errflag. When I do select() and it's interrupted via SIGINT, I check errflag to see if it's SIGINT (have own constant assigned to errflag). However, the handler can be late and errflag isn't yet set. How to defer processing before handler's resolution on errflag? Or how to implement this correctly?

Also, in one code path select() returns -1 on Ctrl-C, errno is EINTR. Here handler is never late. In other path select() returns -1, errno is also EINTR, but handler outputs log message little later and is late, my errflag checks are already performed.


Solution

  • However, the handler can be late and errflag isn't yet set.

    Er, what? No, it can't be "late". Something else is wrong here.

    Signal handlers interrupt normal program flow -- when SIGINT is received, your handler runs, and control flow is only released to the rest of your program when the signal handler exits.

    What you do need to make sure of is that errflag is declared as volatile, so that the compiler will not make undue assumptions about when its value can change.

    What you also need to keep in mind is that printf() is not safe to use in signal handlers, as it may use global buffers which can be left in an inconsistent state during signal handling. Generally speaking, very few things are safe to do during a signal handler besides setting volatile global variables or exiting. Trying to use printf() in a signal handler may result in inconsistent, confusing results; the output should not be used as a reliable indicator of what actually happened in your program!