pause() signal handler
Asked Answered
Y

2

8

The pause() function blocks until a signal arrives. Assuming the process got a signal and pause() returned, does the signal handler will be executed before the code that follows the pause() call, or the result is unexpected?

Example:

void sigusr1_handler() 
{
   // .. handler code
}

void main() 
{
   // .. bind handler to SIGUSR1

   pause(); // wait for SIGUSR1
   // some more code
}

Does "some more code" will always be executed after sigusr1_handler() has finished, or there is a race condition? If so, what is the solution?
I cannot think of anything besides busy-waiting, but then the pause won't be needed at all..

Yulma answered 11/6, 2017 at 13:49 Comment(1)
"or the result is unexpected" - How would we know what you expect?Shelbashelbi
T
10

Citing from the man page for pause(2):

pause() returns only when a signal was caught and the signal-catching function returned. In this case, pause() returns -1, and errno is set to EINTR.

You can be sure that your signal handler runs before some more code.

Trenatrenail answered 11/6, 2017 at 13:57 Comment(0)
T
3

Signal handlers do not run concurrently; they interrupt the thread that handles them, and the interrupted flow only continues when the signal handler returns.

However, there may be other race conditions associated with your example; with just sparse pseudo-code and not a full explanation of your usage case, it's hard to say. For example a different signal might arrive and interrupt the pause before your signal does, and then your handler could end up running later than you expected.

There are several "right ways" to do this instead:

  • write a single byte to a pipe in the signal handler, and read from it in the main flow of execution.
  • sem_post a semaphore from the signal handler, and sem_wait in the main flow of execution.
  • Use sigwaitinfo or sigtimedwait instead of a signal handler.
  • Still use pause, but in a loop:

    while(!signal_handler_finished) pause();
    

    where signal_handler_finished has type volatile sig_atomic_t, and is set to a nonzero value in the signal handler.

Thier answered 11/6, 2017 at 13:58 Comment(1)
Thanks. I also use sig_mask to block other signals in the signal handler. That's why I made my example simple. Just wanted to make sure signal handlers does not run in 'thread style' and thus subject to race conditions. So in my case pause should work fine. Thanks for the additional info!Yulma

© 2022 - 2024 — McMap. All rights reserved.