recvfrom interrupt

Manfred mx2927@gmail.com
Sun Aug 21 15:05:00 GMT 2016


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