【发布时间】:2017-09-10 22:45:19
【问题描述】:
我正在使用 C 中的信号。我的主要功能基本上是使用 fgets(name, 30, stdin) 请求一些输入,然后坐在那里等待。我用alarm(3) 设置了一个警报,然后我重新分配了SIGALRM 来调用一个函数myalarm,它只调用system("say PAY ATTENTION")。但是警报响起后,fgets() 停止等待输入,我的主 fn 继续。即使我将 myalarm 更改为仅设置一些变量并且不对其执行任何操作,也会发生这种情况。
void myalarm(int sig) {
//system("say PAY ATTENTION");
int x = 0;
}
int catch_signal(int sig, void (*handler)(int)) { // when a signal comes in, "catch" it and "handle it" in the way you want
struct sigaction action; // create a new sigaction
action.sa_handler = handler; // set it's sa_handler attribute to the function specified in the header
sigemptyset(&action.sa_mask); // "turn all the signals in the sa_mask off?" "set the sa_mask to contian no signals, i.e. nothing is masked?"
action.sa_flags = 0; // not sure, looks like we aren't using any of the available flags, whatever they may be
return sigaction(sig, &action, NULL); // here is where you actually reassign- now when sig is received, it'll do what action tells it
}
int main() {
if(catch_signal(SIGINT, diediedie)== -1) {
fprintf(stderr, "Can't map the SIGINT handler");
exit(2);
}
if(catch_signal(SIGALRM, myalarm) == -1) {
fprintf(stderr, "Can't map the SIGALAM handler\n");
exit(2);
}
alarm(3);
char name[30];
printf("Enter your name: ");
fgets(name, 30, stdin);
printf("Hello, %s\n", name);
return 0;
}
为什么alarm() 让fgets() 停止等待输入?
编辑:为我的 catch_signal 函数添加了代码,并且根据其中一个 cmets,使用了 sigaction 而不是 signal,但问题仍然存在。
【问题讨论】:
-
参见
man 7 signal,副标题“信号处理程序中断系统调用和库函数” -
我看到这个:“如果对以下接口之一的阻塞调用被信号处理程序中断,那么如果使用了 SA_RESTART 标志,则在信号处理程序返回后,调用将自动重新启动; 否则调用将失败并出现错误 EINTR..." 并且 fgets() 未列为可以重新启动的函数之一。我试图做的事情是不可能的吗?
-
fgets()在后台使用read系统调用。顺便说一句,在我的系统上它没有被中断(Arch Linux x86_64) -
@Retr0spectrum:您的 C 实现可能会检测到 EINTR 并为您重新启动读取。
-
你没有显示
catch_signal(),但我猜你使用signal()而不是sigaction(),这意味着fgets()调用的read()没有重新启动。使用sigaction()来控制它。