Reputation: 21
I want to use alarm()
to set the timeout of recvfrom
. But found that when use signal()
to register a handler for SIGALRM
, and a SIGALRM
has been captured and then invoked the signal handler. But after returned from handler, the recvfrom()
still blocks while there is no data coming and there is no EINTR
error. Why? Does the signal()
set the SA_RESTART
flag automatically?
Here is the code:
signal(SIGALRM, sig_handler);
while(1)
{
alarm(5);
n = recvfrom(sock, buf, BUF_MAX, 0, (struct sockaddr*)&addr, &len);
if(n < 0)
{
if(errno == EINTR)
{
printf("recvfrom timeout\n");
continue;
}
else
{
printf("recvfrom error\n");
}
}
else
{
printf("data: %s\n", buf);
alarm(0);
}
}
void sig_handler(int signo)
{
return;
}
Upvotes: 1
Views: 423
Reputation: 13846
Whether the blocking call is restarted is a platform dependent attribute, according to signal
's man page:
The situation on Linux is as follows:
- The kernel's signal() system call provides System V semantics.
- By default, in glibc 2 and later, the signal() wrapper function does not invoke the kernel system call. Instead, it calls sigaction(2) using flags that supply BSD semantics. This default behavior is provided as long as a suitable feature test macro is defined: _BSD_SOURCE on glibc 2.19 and earlier or _DEFAULT_SOURCE in glibc 2.19 and later. (By default, these macros are defined; see feature_test_macros(7) for details.) If such a feature test macro is not defined, then signal() provides System V semantics.
Since BSD semantics are equivalent to calling sigaction(2)
with the following flags:
sa.sa_flags = SA_RESTART;
and System V semantics does not do SA_RESTART
, what you saw is that your program is doing the BSD way, so you should make sure use the said feature test macros to get defined bahavior of your program.
Upvotes: 1