使用以下信号处理程序,按Ctrl-C
会导致重复调用处理程序,我不知道为什么:
(警告:如果您键入Ctrl-C
,则必须使用kill <pid>
退出程序)
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);
}
所以我知道我对信号处理程序有些不了解。我假设只有SIGCONT
会到达最后一行,因为SIGINT
(例如),当它以默认行为(SIG_DFL
)引发时,应该退出而不是返回。
我也知道我可以将最后一行包装在 if 语句中,该语句仅适用于SIGCONT
,但我真的很想知道为什么它的行为方式不符合我的预期。
问题
- 为什么信号处理程序在无限循环中被调用?
- 如何让处理程序执行有趣的操作,调用默认行为,然后在默认行为未退出程序的情况下重新注册自身?
MCVE
这可以通过将它写入文件sigtest.c
并执行make sigtest
来运行。使用Ctrl-C
提高SIGINT
,并在另一个终端中,准备做ps | grep sigtest
然后kill <pid>
。
#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 exitn");
while (1) {
c = getchar();
printf("got char: %cn", c);
if (c == 'x') { break; }
}
}
我空白了,忘记了信号在处理时被阻止了。这意味着在处理程序返回之前,并且在我将操作从SIG_DFL
设置回自定义处理程序之前,实际上不会引发SIGINT
。因此,它是循环的。
我的示例的工作处理程序如下所示:
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);
}
}