This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

recvfrom interrupt


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)
{
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]