3

这是(部分)我的服务器端代码

void timeout_handler(int value) {
    printf("Handler\n");
    return;
}

int main (int argc, char **argv) {
    [...]
    signal(SIGALRM, timeout_handler);
    alarm(seconds);
    int result = read(input_socket, buffer, sizeof(buffer));
    if (result == -1 && errno == EINTR) {
        printf("read() failed\n");
    }
    [...]
}

input_socket与客户端正确连接的 TCP 套接字在哪里(如果我从客户端发送数据,服务器会接收它们)。

作为警报信号的测试,我尝试只打开并连接套接字客户端而不发送任何数据。我希望输出像

Handler
read() failed

但结果只是Handler消息,然后进程仍然处于活动状态。

为什么read()不失败errno=EINTR

4

1 回答 1

1

同样在 OSX 上,某些系统调用在被信号中断时默认重新启动。

siginterrupt()可以用来改变这种行为。以下行(alarm()调用之前的某处)应该完成让程序按 OP 预期运行的工作:

siginterrupt(SIGALRM, 1);

From the OSX documentation (emphasis by me):

For some system calls, if a signal is caught while the call is executing and the call is prematurely terminated, the call is automatically restarted. Any handler installed with signal(3) will have the SA_RESTART flag set, meaning that any restartable system call will not return on receipt of a signal. The affected system calls include read(2), write(2), sendto(2), recvfrom(2), sendmsg(2), and recvmsg(2) on a communications channel or a low speed device and during a ioctl(2) or wait(2). However, calls that have already committed are not restarted, but instead return a partial success (for example, a short read count). These semantics could be changed with siginterrupt(3).

This is different on Linux for example, where restarting of system call possibly interupted needs to explicitly be requested by the signal sent.

于 2013-08-31T14:09:57.223 回答