[英]Why is not blocking read() interrupted after receiving SIGINT?
有这个代码:
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#define BSIZE 16
static void sigalarm_handler(int signo)
{
//cause SIGINT by returning
return;
}
int main()
{
sigset_t sigset;
ssize_t nbytes;
char buf[BSIZE];
struct sigaction action;
//initialize sigset and signal handler
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
memset(&action, 0, sizeof(action));
action.sa_handler = sigalarm_handler;
sigaction(SIGALRM, &action, NULL);
//infinite loop
while (1)
{
alarm(2);
printf("enter some input (3 chars)\n");
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
//should SIGALRM should interupt read after 2 secs
nbytes = read(fileno(stdin), buf, 3);
sigprocmask(SIG_BLOCK, &sigset, NULL);
if (nbytes < 0)
{
if (errno == EINTR)
{
break;
}
}
buf[3] = '\0';
//sleep should get SIGALRM, which in turn calls sigalarm_handler which generates SIGINT and interupts sleep, but the SIGALRM shouldn't be wasted, because it is prolong until it is unblock and thus next loop should break out
sleep(2);
printf("you wrote: %s\n", buf);
}
}
我希望在 2 秒后中断read()
。 但是读取会不确定地阻塞。 怎么样? SIGINT
不应该中断 read() 吗?
signal()
并不清楚系统调用是中断还是自动重启; 它可能因平台而异。 请参阅手册页,在末尾的“注释/可移植性”部分; 据说在 Linux 上, signal()
使用 BSD 语义,这相当于在sigaction()
中对某些系统调用使用SA_RESTART
(请参阅此页面中的“信号处理程序中断系统调用和库函数”部分)。
sigaction()
提供了更好的控制。
您可以替换signal(SIGALRM, sigalarm_handler);
经过
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler=sigalarm_handler;
sigaction(SIGALRM, &action, NULL);
在调用read()
之后立即放置printf()
) 表明在使用sigaction()
时该调用被中断,但在使用signal()
时不会中断(至少在我的系统上)。
正如问题的评论中所述,循环没有停止的事实本质上是由于算法的笨拙: if
未初始化或不相关的变量进行各种尝试(问题中的代码已更改多次,现在使用nbytes
好的),测试错误的errno
...
这是一个尝试在read()
之后明确情况的示例。
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
nbytes = read(fileno(stdin), buf, 3);
int read_errno=errno; // save errno because the next call to
// sigprogmask() could overwrite it
sigprocmask(SIG_BLOCK, &sigset, NULL);
if(nbytes==0)
{
printf("EOF reached (Control-d for example)\n");
break;
}
if(nbytes<0) // read() failed
{
if(read_errno==EINTR)
{
printf("interrupted by a signal while reading\n");
}
else
{
printf("something really bad happened: %s\n",
strerror(read_errno));
}
break;
}
printf("%d bytes were read\n", (int)nbytes); // read() succeeded
buf[nbytes] = '\0';
printf("you wrote: <%s>\n", buf);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.