Robin McCorkell
Robin McCorkell

Reputation: 764

SIGALRM to interrupt syscall

I need to interrupt a syscall (recvfrom in this case) after a timeout. For this I'm using alarm(), however the resulting SIGALRM kills my process instead of only interrupting the syscall.

I've tried calling signal(SIGALRM, SIG_IGN) to handle the SIGALRM, but this causes the syscall to not be interrupted at all! The only way I've got this to work is by creating a custom empty handler (signal(SIGALRM, alrm_handler)) - the handler does nothing, but it still results in the recvfrom being interrupted without the process being killed.

I understand that the default signal handler (SIG_DFL) will kill the process, but I expected SIG_IGN to ignore the signal but still interrupt the syscall. I straced a test program with SIG_IGN and with a custom empty handler, and they both end up calling rt_sigaction(SIGALRM...) without SA_RESTART. As far as I know, if SA_RESTART was set then the syscall would be restarted automatically, but this is happening with SIG_IGN anyway!

Is there any cleaner way to interrupt a syscall with SIGALRM without needing a custom signal handler?

Upvotes: 1

Views: 1443

Answers (1)

Ross Ridge
Ross Ridge

Reputation: 39551

When you tell the operating system to ignore a signal you shouldn't be surprised if when it's signaled it does nothing and ignores it. POSIX only allows recvfrom to return EINTR if has been interrupted and it's only interrupted if a signal handler is called. When SIG_IGN is set POSIX requires that "delivery of the signal will have no effect on the process."

A better way to to do timeouts on socket operations is to set a timeout on the socket using setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, ...). You'll get either an EAGAIN or EWOULDBLOCK error if it times out.

You might also want to look at select which can potentially eliminate the need to use timeouts.

Upvotes: 3

Related Questions