Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recvfrom() timeout with alarm()

I'm debugging the following code:

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

As described by man 3 siginterrupt the alarm should interrupt the system call, but in my case it doesn't. Alarm handler is invoked, but recvfrom is not interrupted.

However, when a new signal handler is specified with the signal(2) function, the system call is interrupted by default.

If I add siginterrupt(SIGALRM, 1); after setting the alarm handler then recvfrom is interrupted as expected.

What am I missing? What's wrong with my code?

NOTES: Replacing signal with sigaction is not what I'm looking for.

like image 920
Alexandru Avatar asked May 08 '11 18:05

Alexandru


1 Answers

The siginterrupt(3) manpage was incorrect (version 3.33 of the Linux manpage set corrects the error). The default behavior of glibc's signal is to establish a signal that does not interrupt system calls. You can see this for yourself with 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

Note the SA_RESTART in there. You can either keep doing what you're doing -- call siginterrupt(SIGALRM, 1) after establishing the handler -- or you can switch to using sigaction, which will let you set the flags the way you want in the first place. You said you didn't want to do that (why?) but nonetheless that is what I would recommend.

like image 83
zwol Avatar answered Sep 30 '22 16:09

zwol