recvfrom interrupt

Manfred mx2927@gmail.com
Mon Aug 22 13:34:00 GMT 2016


Thanks a lot for the reply.
Indeed signal(2) clarifies the "portability mess" about signal(). This 
probably explains why the code I was debugging used to work in the past 
and not any more now.

The manpage I have for glibc 2.22 is a bit different than yours:
* 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.

So it seems that _DEFAULT_SOURCE is what is triggering BSD semantics.

Thanks again,
M.

On 08/22/2016 03:09 PM, Godmar Back wrote:
> Whether or not the call returns with EINTR depends on whether it is
> restarted upon signal delivery.
> If the system call is restarted, you will not see EINTR on the user side.
>
> You're using signal(2) to set up the handler. Does it set up the
> signal handler with SA_RESTART?
>
> Look at the strace output. On my system (Ubuntu 16 stock) I see:
>
> [pid 12320] rt_sigaction(SIGQUIT, {0x40103c, [QUIT],
> SA_RESTORER|SA_RESTART, 0x7f5cee65d4a0},  <unfinished ...>
>
> Thus, the signal handler is set up to restart.
>
> The man page for signal(2), on the other hand, appears out-of-date. It says:
>
>        * On  glibc  2  and later, if the _BSD_SOURCE feature test
> macro is not defined, then signal() provides System V
>          semantics.  (The default implicit definition of _BSD_SOURCE
> is not provided if one invokes gcc(1)  in  one  of
>          its  standard  modes  (-std=xxx  or -ansi) or defines various
> other feature test macros such as _POSIX_SOURCE,
>          _XOPEN_SOURCE, or _SVID_SOURCE; see feature_test_macros(7).)
>
> I checked that _BSD_SOURCE is not defined, yet signal(2) appears to
> provide BSD semantics.
>
> Conventional wisdom says to avoid signal(2) in favor of sigaction().
>
>  - Godmar
>
>
> On Sun, Aug 21, 2016 at 11:05 AM, Manfred <mx2927@gmail.com> wrote:
>> Hi all,
>>
>> While debugging some old code, I encountered the problem that recvfrom calls
>> do not get interrupted by a signal (SIG_QUIT).
>> The code used to work in the past (a long far away past), anyway I have
>> isolated the behavior in the code below, and reporting here because
>> signal(7) clearly lists recvfrom as one of the calls that should get
>> interrupted by a received signal.
>>
>> Could anyone give a hint on what am I missing here?
>> Thanks in Advance,
>> M.
>>
>>
>> #include <stdio.h>
>> #include <unistd.h>
>>
>> #include <sys/types.h>
>> #include <sys/wait.h>
>> #include <signal.h>
>>
>> #include <sys/socket.h>
>> #include <linux/ipx.h>
>>
>> #include <stdlib.h>
>> #include <string.h>
>> #include <stdint.h>
>> #include <errno.h>
>>
>> #include <netinet/in.h>
>>
>>
>> void child();
>> void sig_quit(int dummy);
>> int create_socket( const char* who, struct sockaddr_ipx* addr, socklen_t*
>> addr_len );
>>
>>
>> int main(int argc, char*argv[])
>> {
>>   int status = 0;
>>
>>   pid_t pid_child = fork();
>>   if(-1 == pid_child)
>>   {
>>     return 1;
>>   }
>>   if(0 == pid_child)
>>   {
>>     child();
>>   }
>>   else
>>   {
>>     puts("parent: running\n");
>>     sleep(3);
>>
>>     puts("parent: signaling the child\n");
>>     kill(pid_child, SIGQUIT);
>>     if(pid_child == waitpid(pid_child, &status, 0))
>>     {
>>       puts("parent: child terminated\n");
>>     }
>>     else
>>     {
>>       puts("parent: ERROR terminating child\n");
>>     }
>>     puts("parent: terminated\n");
>>   }
>>
>>   return 0;
>> }
>>
>> void child()
>> {
>>   int sock = 0;
>>
>>   struct sockaddr_ipx addr;
>>   socklen_t           addr_len = sizeof(addr);
>>
>>   unsigned char buf[256];
>>   ssize_t       buflen = 0;
>>
>>   memset(&addr, 0, sizeof(addr));
>>   addr.sipx_family = AF_IPX;
>>
>>   puts("child: running\n");
>>
>>   signal(SIGQUIT, sig_quit);
>>
>>   if((sock = create_socket("child", &addr, &addr_len)) == -1)
>>   {
>>     puts("child: ERROR creating socket\n");
>>     exit(1);
>>   }
>>
>>   memset(&addr, 0, sizeof(addr));
>>   addr.sipx_family = AF_IPX;
>>   addr_len = sizeof(addr);
>>
>>   puts("child: receiving datagram");
>>   while((buflen = recvfrom(sock, buf, sizeof(buf), 0,
>>       (struct sockaddr*)&addr, &addr_len )) != -1)
>>   {
>>     puts("child: data received\n");
>>     for(ssize_t n = 0; n < buflen; ++n)
>>     {
>>       if(0 < n) printf(", ");
>>       printf("%02x", buf[n]);
>>       if(1) printf("\'%c\'", buf[n]);
>>     }
>>     printf("\n");
>>   }
>>
>>   if(EINTR == errno) puts("child: recvfrom interrupted\n");
>>   else puts("child: ERROR on recvfrom\n");
>>
>>
>>   if(close(sock) == -1)
>>   {
>>     puts("client: ERROR closing socket\n");
>>     exit(1);
>>   }
>>   puts("child: socket closed\n");
>>   puts("child: terminated\n");
>>
>> }
>>
>> int create_socket( const char* who, struct sockaddr_ipx* addr, socklen_t*
>> len )
>> {
>>   int sock = 0;
>>   int opt = 1;
>>
>>   if((sock = socket(AF_IPX, SOCK_DGRAM, 0)) == -1)
>>   {
>>     printf("%s: ERROR creating socket(%d)\n", who, errno);
>>     exit(1);
>>   }
>>   printf("%s: socket created\n", who);
>>
>>   if(setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
>>                 &opt, sizeof(opt)) == -1)
>>   {
>>     printf("%s: ERROR setting socket options(%d)\n", who, errno);
>>     exit(1);
>>   }
>>   printf("%s: socket options set\n", who);
>>
>>   if(bind(sock, (const struct sockaddr*)addr, *len) == -1)
>>   {
>>     printf("%s: ERROR binding socket (%d)\n", who, errno);
>>     exit(1);
>>   }
>>   printf("%s: socket bound\n", who);
>>
>>   if(getsockname(sock, (struct sockaddr*)addr, len) == -1)
>>   {
>>     printf("%s: ERROR retrieving socket address(%d)\n", who, errno);
>>     exit(1);
>>   }
>>
>>   printf("%s: socket address\n\tNET:  %08x\n\tNODE:
>> %02x:%02x:%02x:%02x:%02x:%02x:\n\tPORT: %04x\n\tTYPE: %02x\n",
>>       who,
>>       ntohl(addr->sipx_network),
>>       addr->sipx_node[0], addr->sipx_node[1], addr->sipx_node[2],
>> addr->sipx_node[3], addr->sipx_node[4], addr->sipx_node[5],
>>       ntohs(addr->sipx_port),
>>       addr->sipx_type);
>>
>>   return sock;
>> }
>>
>>
>> void sig_quit(int dummy)
>> {
>> }



More information about the Libc-help mailing list