【问题标题】:sigsuspend(), replace set or add?sigsuspend(),替换设置还是添加?
【发布时间】:2011-07-18 06:04:51
【问题描述】:

根据 sigsuspend() 的手册页,它将用其第一个参数替换当前信号掩码集。在APUE中,我看到一个例子如下。代码可能有点太长,但我不想错过任何内容。

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;
}

输出是:

in critical section: SIGQUIT 
in sig quit: SIGINT SIGQUIT 
after return form sigsuspend: SIGQUIT 
program exit: 

问题出在第二行。 SIGQUIT 仍在信号掩码集中。

应该只是SIGINT,因为sigsuspend 已经用tempset 替换了信号掩码,而SIGINT 仅设置为SIGINT

【问题讨论】:

    标签: c linux signals


    【解决方案1】:

    在执行 SIGQUIT 处理程序时,SIGQUIT 本身被阻塞。这是为了避免意外重新进入处理程序...

    来自POSIX spec for sigaction(你真的应该使用它而不是signal):

    当信号被 sigaction() 安装的信号捕获函数捕获时,会在信号捕获函数的持续时间内计算并安装一个新的信号掩码(或直到调用 sigprocmask() 或 sigsuspend( ) 被制作)。该掩码是通过将当前信号掩码与正在传递的信号的 sa_mask 的值联合形成的,除非设置了 SA_NODEFER 或 SA_RESETHAND,否则将包括正在传递的信号。

    POSIX spec for signal 不太具体:

    当一个信号出现时,func指向一个函数,实现定义是否等价于a:

    信号(信号,SIG_DFL);

    被执行或实现阻止某些实现定义的信号集(至少包括sig)在当前信号处理完成之前发生。

    所以操作系统在信号处理函数的持续时间内简单地将信号添加到掩码是合法的,显然这就是 Linux 所做的。

    【讨论】:

    • 但是,在信号处理功能完成后,操作系统不会将信号掩码重置为旧掩码。有没有办法避免这种情况?
    【解决方案2】:

    因为在执行 SIGQUIT 处理程序时会打印输出“in sig quit: SIGINT SIGQUIT”。它会将 SIGQUIT 添加到信号掩码中,这意味着当前掩码成为 &tempset 和 SIGQUIT 的联合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多