2011-05-08 67 views
7

我调试以下代码:recvfrom的()超时()

signal(SIGALRM, testt);             
alarm(1);                 
result = recvfrom(listening_socket, buf, maxlen, 0, &from, &fromlen); 
printf("stoped\n");   

正如man 3 siginterrupt描述的报警器应中断系统调用,但在我的情况下,它没有。报警处理程序被调用,但recvfrom不会中断。

但是,当使用signal(2)函数指定了新的信号处理程序时,系统调用默认被中断。

如果在设置警报处理程序后添加siginterrupt(SIGALRM, 1);,则recvfrom会按预期中断。

我错过了什么?我的代码有什么问题?

注意:替换signalsigaction是不是我要找的。

+0

请注意'siginterrupt(3)'在POSIX.1-2008中被标记为过时。 – ninjalj 2011-05-08 20:00:57

回答

9

siginterrupt(3)联机帮助页不正确(Linux联机帮助页集的version 3.33更正了错误)。 glibc的signal的默认行为是建立一个信号,确认不是中断系统调用。你可以用strace看到自己这一点:

void handler(int unused) {} 
int main(void) 
{ 
    signal(SIGALRM, handler); 
} 

⟶

$ strace -e trace=rt_sigaction ./a.out 
rt_sigaction(SIGALRM, 
      {0x4005b4, [ALRM], SA_RESTORER|SA_RESTART, 0x7fe732d3d490}, 
      {SIG_DFL, [], 0}, 8) = 0 

注意那里的SA_RESTART。你可以继续做你正在做的事情 - 在建立处理程序之后调用siginterrupt(SIGALRM, 1) - 或者你可以切换到使用sigaction,这可以让你按照自己想要的方式设置标志。你说你不想这么做(为什么?)但是,这是我会推荐的。

+0

TIL strace -e trace = rt_sigaction。这不是我的代码,建立处理程序。 – Alexandru 2011-05-08 18:35:50

+1

@Zack:手册页没有错,只是错误引用。完整的引用是:'如果flag参数为false(0),那么如果被指定的信号sig中断,则系统调用将被重新启动。这是Linux中的默认行为。但是,当使用signal(2)函数指定一个新的信号处理程序时,系统调用会被默认中断。# – ninjalj 2011-05-08 19:05:34

+0

@ninjalj:我觉得我太累了,为什么第一句与'signal() ? – Alexandru 2011-05-08 19:40:11