这是很难说究竟是什么错误没有看到代码的其余部分,但至少有一个问题,你的代码显示:
之前返回,sigsuspend(2)
恢复被调用时处于活动状态的信号掩码。如果您在调用sigsuspend(2)
之前没有相应地更改过程的信号模板,则在从sigsuspend(2)
返回并测试其他未决信号可能被传送的值之间存在一段时间窗口(或者甚至可能是新信号生成并交付)。如果捕获到这些信号并且处理程序将flag
的值更改为另一个值,则“丢失”SIGUSR2
的处理程序所做的更新。
例如,考虑这样的程序:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
volatile sig_atomic_t flag;
void handler1(int signo) {
printf("In handler1\n");
flag = 1;
}
void handler2(int signo) {
printf("In handler2\n");
flag = 2;
}
int main(void) {
struct sigaction sigact;
sigact.sa_handler = handler1;
sigact.sa_flags = 0;
sigfillset(&sigact.sa_mask);
if (sigaction(SIGUSR1, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigact.sa_handler = handler2;
if (sigaction(SIGUSR2, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGUSR1);
sigsuspend(&mask);
printf("%d\n", flag);
return 0;
}
它惹人SIGUSR1
和SIGUSR2
,每块信号除了SIGUSR1
,然后调用sigsuspend(2)
。
运行它,然后发送它SIGUSR2
,然后SIGUSR1
。这确保了在SIGUSR1
被发现并采取行动之前有一个待处理的信号。这也导致SIGUSR2
要尽快SIGUSR2
畅通传递,之后sigsuspend(2)
收益恰好(因为我们没有接触过程中的信号掩码):
[email protected]:~/dev$ kill -SIGUSR2 29755
[email protected]:~/dev$ kill -SIGUSR1 29755
输出:
[email protected]:~/dev$ ./a.out
In handler1
In handler2
2
怎么办你解决它?只要确保将进程的信号掩码设置为与您在sigsuspend(2)
中使用的掩码相同,以便它不会错误地恢复掩码。这是因为调用sigsuspend(2)
前加入这个简单:
if (sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
perror("sigprocmask()");
exit(EXIT_FAILURE);
}
因此,更新的程序:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
volatile sig_atomic_t flag;
void handler1(int signo) {
printf("In handler1\n");
flag = 1;
}
void handler2(int signo) {
printf("In handler2\n");
flag = 2;
}
int main(void) {
struct sigaction sigact;
sigact.sa_handler = handler1;
sigact.sa_flags = 0;
sigfillset(&sigact.sa_mask);
if (sigaction(SIGUSR1, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigact.sa_handler = handler2;
if (sigaction(SIGUSR2, &sigact, NULL) < 0) {
perror("sigaction()");
exit(EXIT_FAILURE);
}
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGUSR1);
if (sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
perror("sigprocmask()");
exit(EXIT_FAILURE);
}
sigsuspend(&mask);
printf("%d\n", flag);
return 0;
}
可正常工作:它保证没有其他信号处理程序将窗口之间执行时间sigsuspend(2)
返回并且您测试flag
。
另一个重要提示:我不知道如何设置信号处理程序,但是如果您使用的是signal(2)
,那么请不要:它的语义是依赖于平台的,它可能不像您想要的那样工作。您应该使用sigaction(2)
,正如我在示例程序中所示。需要使用sigfillset(&sigact.sa_mask)
行来确保当信号处理程序正在运行时,所有其他信号仍然被阻塞 - 否则,在执行SIGUSR1
的处理程序过程中传送信号可能会调用另一个更改标志的处理程序。
请向我们展示一个[MCVE](http://stackoverflow.com/help/mcve)。 – pilcrow