我有以下代码。当我使用gnu扩展(-std=gnu99)编译它时,程序将在结束之前捕获5SIGINT(我希望如此)。在没有它的情况下编译时(-std=c99)在第二行之后结束(并且只输出一行)。
我遗漏了什么?
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
int int_stage = 0;
int got_signal = 0;
void sigint(int parameter)
{
(void)parameter;
got_signal = 1;
int_stage++;
}
int main()
{
signal(SIGINT,sigint);
while(1)
{
if (got_signal)
{
got_signal = 0;
puts("still alive");
if (int_stage >= 5) exit(1);
}
}
return 0;
}发布于 2011-11-28 03:11:59
使用sigaction(2)而不是signal(2)。
Linux手册页的可移植性部分特别包含以下内容:
在最初的UNIX系统中,当通过传递信号来调用使用signal()建立的处理程序时,该信号的处理将被重置为SIG_DFL,并且系统不会阻止该信号的进一步实例的传递。System V也为signal()提供了这些语义。这很糟糕,因为在处理程序有机会重新建立自己之前,信号可能会再次传递。此外,相同信号的快速传递可能导致处理程序的递归调用。
BSD通过更改信号处理的语义改进了这种情况(但不幸的是,在使用signal ()建立处理程序时,它默默地更改了语义)。在BSD上,当调用信号处理程序时,不会重置信号处理,并且在处理程序执行时阻止传递信号的更多实例。
Linux上的情况如下:
在glibc 2和更高版本上,如果未定义信号特性测试宏,则_BSD_SOURCE ()提供System V语义。(请参见feature_test_macros(7).),如果在_BSD_SOURCE的标准模式之一(-std=xxx或-ansi)中调用gcc(1)或定义各种其他功能测试宏(如_POSIX_SOURCE、_XOPEN_SOURCE或_SVID_SOURCE),则不会提供默认的隐式定义_XOPEN_SOURCE
使用std=gnu99,您将获得BSD语义。使用-std=c99,您将获得System V语义。因此,在一种情况下(BSD)“重新安装”信号处理程序,而在另一种情况下(System V)将信号处理程序重置回SIG_DFL。
发布于 2011-11-28 03:17:45
问题是signal还会重置信号处理机制,您必须将sigint重置为信号处理程序。从手册中
在最初的UNIX系统中,当通过传递信号来调用使用signal()建立的处理程序时,该信号的处理将被重置为SIG_DFL,并且系统不会阻止该信号的进一步实例的传递。System V也为signal()提供了这些语义。这很糟糕,因为在处理程序有机会重新建立自己之前,信号可能会再次传递。此外,相同信号的快速传递可能导致处理程序的递归调用。
这就是如何使用旧的过时的signal()调用来实现它。注意int_stage和got_signal必须是sig_atomic_t的,你也可以只调用异步安全函数,查看here的列表。
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
sig_atomic_t int_stage = 0;
sig_atomic_t got_signal = 0;
void sigint(int parameter)
{
(void)parameter;
got_signal = 1;
int_stage++;
}
int main()
{
signal(SIGINT,sigint);
while(1)
{
if (got_signal)
{
signal(SIGINT,sigint);
got_signal = 0;
puts("still alive");
if (int_stage >= 5) exit(1);
}
}
return 0;
}请考虑使用sigaction或sigwait。
Sigaction实际上也有同样的想法,但重新初始化信号处理程序并不是胡说八道。Sigwait会停止你的线程,直到收到一个信号。因此,对于sigwait,您可以调用任何函数或处理任何数据。如果您愿意,我可以向您展示示例代码。
发布于 2011-11-28 03:12:20
我同意Ethan Steinberg的观点--“忙碌的等待”是非常错误的。
但问题是您无法重置信号处理程序。AFAIK,您必须使用任何版本的C执行此操作(再次调用"signal(SIGINT,sigint)“)。
https://stackoverflow.com/questions/8288164
复制相似问题