开发者

sigsuspend(), replace set or add?

开发者 https://www.devze.com 2023-03-20 19:21 出处:网络
As per the man page of sigsuspend(), it will replace the current signal mask set with its 1st parameter. In APUE, I saw an example as follows. The code maybe a little too long but I don\'t want to mis

As per the man page of sigsuspend(), it will replace the current signal mask set with its 1st parameter. In APUE, I saw an example as follows. The code maybe a little too long but I don't want to miss anything.

int pr_mask(char *s)
{
    sigset_t sigset;

    sigprocmask(0, NULL, &sigset);

    printf("%s: ", s);

    if(sigismember(&sigset, SIGINT)) printf("SIGINT ");
    if(sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");
    if(sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
    if(sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
    /* ..... */

    printf("\n");
    return 0;
}

void sig_quit(int signo)
{
    pr_mask("in sig quit");
}

int main()
{
    sigset_t new, old, tempset;

    signal(SIGQUIT, sig_quit);

    sigemptyset(&tempset);
    sigaddset(&tempset, SIGINT);

    sigemptyset(&new);
    sigaddset(&new, SIGQUIT);
    sigprocmask(SIG_BLOCK, &new, &old);

    pr_mask("in critical section");
    /* critical section */

    sigsuspend(&tempset);
    pr_mask("after return form sigsuspend");

    sigprocmask(SIG_UNBLOCK, &new, NULL);
    pr_mask("program exit");

    return 0;
}

Output is:

in critical section: SIGQUIT 
in sig quit: SIGINT SIGQUIT 
after return form sigsuspend: SIGQUIT 
program ex开发者_开发百科it: 

The problem is the second line. The SIGQUIT is still in the signal mask set.

Should it be only SIGINT as sigsuspend has already replaced the signal mask with tempset, which is set to SIGINT only?


While executing the SIGQUIT handler, SIGQUIT itself is blocked. This is to avoid re-entering the handler by accident...

From the POSIX spec for sigaction (which you really should use instead of signal):

When a signal is caught by a signal-catching function installed by sigaction(), a new signal mask is calculated and installed for the duration of the signal-catching function (or until a call to either sigprocmask() or sigsuspend() is made). This mask is formed by taking the union of the current signal mask and the value of the sa_mask for the signal being delivered, and unless SA_NODEFER or SA_RESETHAND is set, then including the signal being delivered.

The POSIX spec for signal is a little less specific:

When a signal occurs, and func points to a function, it is implementation-defined whether the equivalent of a:

signal(sig, SIG_DFL);

is executed or the implementation prevents some implementation-defined set of signals (at least including sig) from occurring until the current signal handling has completed.

So it is legal for the OS to simply add the signal to the mask for the duration of the signal-handling function, and apparently that is what Linux does.


because the output "in sig quit: SIGINT SIGQUIT " is printed while executing the SIGQUIT handler.it would add the SIGQUIT to the signal mask, that means the current mask become the union of &tempset and the SIGQUIT.

0

精彩评论

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