From: jik@athena.mit.edu (Jonathan I. Kamens)
Subject: Re: Which pipe sent SIGPIPE w/o trying to write to it??
Organization: Massachusetts Institute of Technology
Date: Fri, 10 Apr 1992 15:39:56 GMT

In article <1992Apr10.140611.18715@ringer.cs.utsa.edu> rrybacki@ringer.cs.utsa.edu (Richard M. Rybacki) writes:
   In article <92100.170337PJS100T@ODUVM.BITNET> PJS100T@ODUVM.BITNET (Pam Skillman) writes:
   >Here's the situation:  I've got several pipes to several different processes
   >and I receive a SIGPIPE.  I don't want to try to write anything to each of
   >these pipes as some of the processes are running tools and such and I don't
   >want anything I send interpreted by them.  Is there a way to do this??  A
   >type of polling without having to write??  Thanks in advance!!

   A socket which has been closed at the remote end will be make ready to
   read on the local end, and the read will return a count of zero bytes.
   After receiving the SIGPIPE, you could do a select so see which fds are
   ready to read from.  Those which have zero bytes have been closed at the
   remote end.  For each fd retunred by select, you could do something like:

	   if (ioctl(fd, FIONREAD, &bytes) == -1 || bytes == 0)
		   ...

Wrong.  Your answer is correct when two-way sockets are being
discussed.  However, note that the original poster said that pipes
were being used, and pipes are one-way communication channels.  She
said she was using the WRITE end of the pipe and wanted to determine
if the process on the other end had died, and you can't do that by
doing select() or ioctl() on that end of the pipe.

Consider this test program:

#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>

extern int errno;

main()
{
     int thepipe[2], readpipe, writepipe;
     int nfound, nfds;
     fd_set readfds;
    
     pipe(thepipe);

     readpipe = thepipe[0];
     writepipe = thepipe[1];

     printf("readpipe = %d, writepipe = %d.\n", readpipe, writepipe);
     
     nfds = writepipe + 1;
     FD_ZERO(&readfds);
     FD_SET(writepipe, &readfds);

     nfound = select(nfds, &readfds, 0, 0, 0);
     if (nfound > 0) {
	  int bytes;
	  char buf[1];
	  int res;
	  printf("Write end is ready for read before closing read end!\n");
	  res = read(writepipe, buf, 1);
	  if (res >= 0) {
	       printf("\tread %d bytes.\n", res);
	  }
	  else {
	       printf("\terrno is %d.\n", errno);
	  }
	  ioctl(writepipe, FIONREAD, &bytes);
	  printf("\tFIONREAD returns %d.\n", bytes);
     }

     close(readpipe);

     FD_ZERO(&readfds);
     FD_SET(writepipe, &readfds);

     nfound = select(nfds, &readfds, 0, 0, 0);
     if (nfound > 0) {
	  int bytes;
	  char buf[1];
	  int res;
	  printf("Write end is ready for read after closing read end!\n");
	  res = read(writepipe, buf, 1);
	  if (res >= 0) {
	       printf("\tread %d bytes.\n", res);
	  }
	  else {
	       printf("\terrno is %d.\n", errno);
	  }
	  ioctl(writepipe, FIONREAD, &bytes);
	  printf("\tFIONREAD returns %d.\n", bytes);
     }

     exit(0);
}

On my system, this is its output:

readpipe = 3, writepipe = 4.
Write end is ready for read before closing read end!
	errno is 9.
	FIONREAD returns 0.
Write end is ready for read after closing read end!
	errno is 9.
	FIONREAD returns 0.

Note that select indicates that the write end of the pipe is ready to
be read *before* the read end has been closed, that a read on the
write end of the pipe always fails, and that FIONREAD on the write end
of a pipe always returns 0.

-- 
Jonathan Kamens						jik@MIT.Edu
MIT Information Systems/Athena		    Moderator, news.answers
    (Send correspondence related to the news.answers newsgroup
	{and ONLY correspondence related to the newsgroup}
		 to news-answers-request@MIT.Edu.)