SIGPIPE not sent to writer on AF_INET sockets

Keith Packard keithp at azure.UUCP
Wed Jul 24 10:18:55 AEST 1985


I have been trying to use INET domain sockets in an application that
previously used UNIX domain sockets.  I wanted to use INET sockets so
I could use my application from multiple machines and, although that
portion works correctly, I have discovered an undocumented "feature"
of INET sockets:  when a process writes on a socket without a reader
the familiar SIGPIPE signal is not sent and, in fact, *no* error
indication at all!  Have I done something wrong? 

Below is a shell-archive that contains two sets of programs, they are
effectively identical except that one uses unix domain sockets
and the other uses inet sockets.  Type "make test" to see if
SIGPIPE is sent for inet sockets, the expected output for each set
is:

	hello world
	SIGPIPE caught

Keith Packard
...!tektronix!azure!keithp

------------------------a clasic shell archive------------------
: files:
:
: Makefile
: binet.c
: bunix.c
: cinet.c
: cunix.c
:
sed 's/^X//' << \%%%%%%EOF%%%%%%% >Makefile
X#
X#	makefile for SIGPIPE test
X#
XPROGS=bunix cunix binet cinet
X
Xtest: all
X	bunix
X	cunix
X	binet
X	cinet
X
Xall: $(PROGS)
X
Xbunix: bunix.o
X	cc -o bunix bunix.o
Xcunix: cunix.o
X	cc -o cunix cunix.o
Xbinet: binet.o
X	cc -o binet binet.o
Xcinet: cinet.o
X	cc -o cinet cinet.o
%%%%%%EOF%%%%%%%
sed 's/^X//' << \%%%%%%EOF%%%%%%% >binet.c
X/*
X *	server process, AF_INET version
X */
X# include	<sys/types.h>
X# include	<sys/socket.h>
X# include	<netinet/in.h>
X
Xstruct sockaddr_in	addr = { AF_INET, 29997 };
X
Xmain ()
X{
X	int	s, t, cnt;
X	char	buf[1024];
X
X	if ((s = socket (AF_INET, SOCK_STREAM, 0)) == -1)
X		perror ("server socket");
X	setsockopt (s, SOL_SOCKET, SO_REUSEADDR, 0, 0);
X	if (bind (s, &addr, sizeof (addr)) == -1)
X		perror ("server bind");
X	if (listen (s, 5) == -1)
X		perror ("server listen");
X	if (fork () > 0)
X		_exit (0);
X	cnt = sizeof (addr);
X	if ((t = accept (s, &addr, &cnt)) == -1)
X		perror ("server accept");
X	if (shutdown (t, 1) == -1)
X		perror ("server shutdown");
X	/*
X	 *	read just one message and
X	 *	carefully close the sockets
X	 */
X	if ((cnt = read (t, buf, 1024)) == -1)
X		perror ("server read");
X	if (write (1, buf, cnt) != cnt)
X		perror ("server write");
X	close (t);
X	close (s);
X	_exit (0);
X}
%%%%%%EOF%%%%%%%
sed 's/^X//' << \%%%%%%EOF%%%%%%% >bunix.c
X/*
X *	server process, AF_UNIX version
X */
X# include	<sys/types.h>
X# include	<sys/socket.h>
X# include	<sys/un.h>
X
Xstruct sockaddr_un	addr = { AF_UNIX, "socket" };
X
Xmain ()
X{
X	int	s, t, cnt;
X	char	buf[1024];
X
X	if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1)
X		perror ("server socket");
X	setsockopt (s, SOL_SOCKET, SO_REUSEADDR, 0, 0);
X	if (bind (s, &addr, sizeof (addr)-2) == -1)
X		perror ("server bind");
X	if (listen (s, 5) == -1)
X		perror ("server listen");
X	if (fork () > 0)
X		_exit (0);
X	cnt = sizeof (addr);
X	if ((t = accept (s, &addr, &cnt)) == -1)
X		perror ("server accept");
X	if (shutdown (t, 1) == -1)
X		perror ("server shutdown");
X	/*
X	 *	read just one message and
X	 *	carefully close the sockets
X	 */
X	if ((cnt = read (t, buf, 1024)) == -1)
X		perror ("server read");
X	if (write (1, buf, cnt) != cnt)
X		perror ("server write");
X	close (t);
X	close (s);
X	unlink ("socket");
X	_exit (0);
X}
%%%%%%EOF%%%%%%%
sed 's/^X//' << \%%%%%%EOF%%%%%%% >cinet.c
X/*
X *	client process, AF_INET version
X */
X
X# include	<sys/types.h>
X# include	<sys/socket.h>
X# include	<netinet/in.h>
X# include	<signal.h>
X# include	<netdb.h>
X
Xstruct sockaddr_in	addr = { AF_INET, 29997 };
X
Xmain ()
X{
X	int	s, t, cnt;
X	char	buf[1024];
X	int	pipedead ();
X
X	struct hostent	*gethostbyname (), *hostent;
X	/*
X	 *	local host address
X	 */
X	hostent = gethostbyname ("localhost");
X	addr.sin_addr.s_addr = *(int *)hostent->h_addr;
X	s = socket (AF_INET, SOCK_STREAM, 0);
X	if (connect (s, &addr, sizeof (addr)) == -1)
X		perror ("socket connect");
X	shutdown (s, 0);
X	/*
X	 *	write one message and wait a bit,
X	 *	this way the server will read from
X	 *	the socket and exit before the
X	 *	second write
X	 */
X	if (write (s, "hello world\n", 12) != 12)
X		perror ("first write in client");
X	sleep (2);
X	signal (SIGPIPE, pipedead);
X	/*
X	 *	this *should* cause a SIGPIPE
X	 *	to be sent to this process as
X	 *	the server has exited at this time
X	 */
X	if (write (s, "sigpipe?\n", 9) != 9)
X		perror ("second write in client");
X	exit (0);
X}
X
Xpipedead ()
X{
X	write (2, "SIGPIPE caught\n", 15);
X	_exit (0);
X}
%%%%%%EOF%%%%%%%
sed 's/^X//' << \%%%%%%EOF%%%%%%% >cunix.c
X/*
X *	client process, AF_UNIX version
X */
X
X# include	<sys/types.h>
X# include	<sys/socket.h>
X# include	<sys/un.h>
X# include	<signal.h>
X
Xstruct sockaddr_un	addr = { AF_UNIX, "socket" };
X
Xmain ()
X{
X	int	s, t, cnt;
X	char	buf[1024];
X	int	pipedead ();
X
X	s = socket (AF_UNIX, SOCK_STREAM, 0);
X	if (connect (s, &addr, sizeof (addr)-2) == -1)
X		perror ("socket connect");
X	shutdown (s, 0);
X	/*
X	 *	write one message and wait a bit,
X	 *	this way the server will read from
X	 *	the socket and exit before the
X	 *	second write
X	 */
X	if (write (s, "hello world\n", 12) != 12)
X		perror ("first write in client");
X	sleep (2);
X	signal (SIGPIPE, pipedead);
X	/*
X	 *	this *should* cause a SIGPIPE
X	 *	to be sent to this process as
X	 *	the server has exited at this time
X	 */
X	if (write (s, "sigpipe?\n", 9) != 9)
X		perror ("second write in client");
X	exit (0);
X}
X
Xpipedead ()
X{
X	write (2, "SIGPIPE caught\n", 15);
X	_exit (0);
X}
%%%%%%EOF%%%%%%%



More information about the Comp.unix.wizards mailing list