开发者

What's the problem of pause() at all?

According to this paragraph ,the following has problem:

 /* usr_interrupt is set开发者_Go百科 by the signal handler.  */
 if (!usr_interrupt)
   pause ();
 
 /* Do work once the signal arrives.  */
 ...

And should use sigsuspend instead.

But I still don't see what the problem is with pause and how sigsuspend solves it,

anyone can explain in more details?


Let's examine what happens when a signal arrives after you've checked usr_interrupt but before you call pause:

main thread                            signal handler
-----------                            --------------
if (!usr_interrupt)
// this is true                        // signal kicks up handler
                                       usr_interrupt = 1;
                                       // handler finishes
pause();
// will wait for signal

You can see in that case that you've missed the signal. Extremely important if there is no further signal incoming since your program will never action it. That's what's known as a race condition. Now let's see what happens with sigsuspend:

main thread                            signal handler
-----------                            --------------
// set up to delay signal.
sigemptyset (&mask);
sigaddset (&mask, SIGUSR1);

// this will delay (block) signal.
// possibly do this first if USR1
//   may be blocked already (check!):
//   sigprocmask (SIG_UNBLOCK, &mask, &old);
sigprocmask (SIG_BLOCK, &mask, &old);

if (!usr_interrupt)
                                       // signal arrives, delayed.
// unblock signal/wait (atomically).
sigsuspend (&old);
                                       // delayed handler start.
                                       usr_interrupt = 1;
                                       // handler finishes.
// sigsuspend returns, clean up.
sigprocmask (SIG_UNBLOCK, &mask, NULL);

In this case, there is no race condition since the signal is delayed until the main thread is ready for it.


This is a classic race condition.

Main                | Signal handler
--------------------|-----------------------
// at this point,   |
// no signal has    |
// arrived, so we   |
// enter the if     |
                    |
if (!usr_interrupt) | 
                    | {signal arrives...}
                    | usr_interrupt = 1;
                    | {...handler finishes}
pause();            |
                    |
// uh-oh, we missed |
// the signal!      |

Now the pause() won't get unblocked until the next signal arrives (which may never happen depending on the program).

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜