This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
recvfrom interrupt
- From: Manfred <mx2927 at gmail dot com>
- To: libc-help at sourceware dot org
- Date: Sun, 21 Aug 2016 17:05:25 +0200
- Subject: recvfrom interrupt
- Authentication-results: sourceware.org; auth=none
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)
{
}