C 重新注册信号处理程序会导致无限循环
对于以下信号处理程序,按Ctrl-C会导致重复调用处理程序,我不知道为什么: (警告:如果键入C 重新注册信号处理程序会导致无限循环,c,signals,posix,infinite-loop,sigint,C,Signals,Posix,Infinite Loop,Sigint,对于以下信号处理程序,按Ctrl-C会导致重复调用处理程序,我不知道为什么: (警告:如果键入Ctrl-C,则必须使用kill退出程序) 所以我知道我对信号处理程序有些不了解。我假设只有SIGCONT会到达最后一行,因为SIGINT(例如),当它以默认行为(SIG_DFL)引发时,应该退出而不返回 我还知道,我可以将最后一行封装在一个if语句中,该语句只对SIGCONT执行,但我真的想知道为什么它的行为不符合我的预期 问题: 为什么在无限循环中调用信号处理程序 我如何让一个处理程序做一些有趣的事
Ctrl-C
,则必须使用kill
退出程序)
所以我知道我对信号处理程序有些不了解。我假设只有SIGCONT
会到达最后一行,因为SIGINT
(例如),当它以默认行为(SIG_DFL
)引发时,应该退出而不返回
我还知道,我可以将最后一行封装在一个if语句中,该语句只对SIGCONT
执行,但我真的想知道为什么它的行为不符合我的预期
问题:
sigtest.c
并执行make sigtest
来运行。使用Ctrl-C
提升SIGINT
,在另一个终端中,准备执行ps | grep sigtest
,然后执行kill
#包括
#包括
#包括
#包括
静态无效处理程序(int sig){
//做些有趣的事
//这样我就能知道我是否在一个无限循环中
写(1,“A”,1);
//提高正常的信号行为
//这确保了正常的信号行为
//例如,如果使用Ctrl-C,则以代码130退出
信号(sig,sig_DFL);
提高(sig);
//重新注册处理程序
//这样,如果信号没有退出程序和信号
//如果以后再次发送,则此处理程序将再次运行
信号(信号发生器,处理器);
}
内部主(空){
字符c;
信号(SIGINT,handler);
信号(SIGTSTP,处理器);
信号(SIGCONT,处理器);
printf(“键入“x”和“回车”退出\n”);
而(1){
c=getchar();
printf(“获取字符:%c\n”,c);
如果(c='x'){break;}
}
}
我屏蔽了,忘记了信号在处理时被屏蔽。这意味着在处理程序返回之前,SIGINT
实际上不会被引发,并且在我将操作从SIG\u DFL
设置回我的自定义处理程序之后。因此,它是循环的
我的示例的工作处理程序如下所示:
static void handler(int sig) {
if (sig == SIGCONT) {
// do something interesting
signal(sig, handler);
signal(SIGTSTP, handler);
} else {
// do something else interesting
signal(sig, SIG_DFL);
raise(sig);
}
}
呃,我忘了:正在处理的信号在处理时被阻止,因此在我的处理程序返回后才调用
raise
,默认行为由最后一行对所有内容启用…signal()
,不建议使用,man signal
:“避免使用它:改用sigaction(2)”@cdarke我认为sigaction
处理程序也会阻止他们正在处理的信号,因此我认为这与问题无关。但是我同意你的看法。@GregSchmit No与信号
,传递的信号没有被阻止(至少没有指定),这是你应该使用sigaction
的原因之一。我觉得这很奇怪。为什么要在SIG处理程序中间更改SIG处理程序?您没有跟踪上一个处理程序的值是什么,因此对于您拥有的任何实现,您似乎都脱离了脚本。其思想是参与一些操作,然后继续执行信号处理程序的默认行为SIGCONT
和SIGTSTP
是特殊情况,因为它们可能会被多次调用,因为它们不会导致程序退出。@jwdonahue最初的问题是一个更改termios
设置的软件。如果有人点击了Ctrl-C
,我想恢复termios
的更改,但随后继续正常的信号行为(如使用代码130退出)。但后来我遇到了一些问题,有人按了Ctrl-Z
,然后又按了fg
。要处理这个问题,我必须确保在SIGCONT
上重新注册我的信号处理程序,否则如果他们注册两次,那么termios
设置就会关闭。@jwdonahue谢谢!是的,我的问题是在Ctrl-Z
和fg
(分别是signalsSIGTSTP
和SIGCONT
)的情况下必须重新注册处理程序,否则事情只会在第一次运行。所以听起来你真的需要两个信号处理程序,每种类型一个。但我认为你应该约束你的管理者。某些地方的静态模块初始化可能也有自己的信号处理程序。
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void handler(int sig) {
// do something interesting
// write so I can see if I'm in an infinite loop
write(1, "A", 1);
// raise normal signal behavior
// this ensures normal signal behavior
// for example, exiting with code 130 if Ctrl-C is used
signal(sig, SIG_DFL);
raise(sig);
// re-register handler
// that way, if signal doesn't exit the program and the signal
// is sent again in the future, this handler will run again
signal(sig, handler);
}
int main(void) {
char c;
signal(SIGINT, handler);
signal(SIGTSTP, handler);
signal(SIGCONT, handler);
printf("type 'x' and 'Enter' to exit\n");
while (1) {
c = getchar();
printf("got char: %c\n", c);
if (c == 'x') { break; }
}
}
static void handler(int sig) {
if (sig == SIGCONT) {
// do something interesting
signal(sig, handler);
signal(SIGTSTP, handler);
} else {
// do something else interesting
signal(sig, SIG_DFL);
raise(sig);
}
}