[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Rewriting hurdselect.c: How to detect that a file descriptor has disappeared?



Hello,

I'm working on a modified hurdselect.c, the poll() part, to enable file
descriptors being bogus, as allowed by POSIX. That case is now solved,
and the revent reported is POLLNVAL. What remains to do to is to return
the POLHUP event (and POLLERR). 

Using modified code from gnulib, attached, a case to check for is: open
a pipe getting both a read and write fs, write, read, close the read
fs, and poll. This case should be detected by hurdselect. Currently it
does not. 

The construct used in hurdselect is the mach_msg() function:

__mach_msg (&msg.head, MACH_RCV_MSG | options, 0, sizeof msg, portset,
to, MACH_PORT_NULL)

This function call only has parameters set for reading. Can a
subsequent call using MACH_SEND_MSG parameters and messages be used to
find out? (or setting both READ and RCV parameters and messages in the
same function call above) If not, how to find out that the read part of
the pipe has been closed (within hurdselect, not the application)

Thanks!
/* File: test_closing a file descriptor */

#include <poll.h>
#include <stdio.h>
#include <unistd.h>

/* Test poll(2) on pipes.  */

static int
test_pipe (void)
{
  int fd[2];
  char buf[3];
  pipe (fd);
  struct pollfd pfd;
  int nfound = -1;

  pfd.fd = fd[1];
  pfd.events = POLLIN | POLLOUT;
  pfd.revents = 0;

  printf ("Pipe created: Read fd[0] = %d, Write fd[1] = %d\n", fd[0], fd[1]);
  write (fd[1], "foo", 3);
  read (fd[0], buf, 3);
  close (fd[0]);
  printf ("After closing fd[0] = %d\n", fd[0]);
  printf ("Input: pfd.events = (POLLIN | POLLOUT) = %d\n", pfd.events);
  nfound = poll (&pfd, 1, -1);
  printf ("Output: pfd.revents = %d\n", pfd.revents);
  printf("Result: pfd.revents & (POLLHUP | POLLERR) = %d & %d = %d\n", pfd.revents, (POLLHUP | POLLERR), pfd.revents & (POLLHUP | POLLERR));
  if ((pfd.revents & (POLLHUP | POLLERR)) == 0)
    printf ("ERROR: expecting (POLLHUP | POLLERR) after shutdown\n");

  close (fd[1]);

  return nfound;
}


int
main ()
{
  int result = -1;

  printf ("\npoll parameters:\n");
  printf ("POLLIN  = %2d, POLLPRI = %2d, POLLOUT  = %2d\n", POLLIN, POLLPRI,POLLOUT);
  printf ("POLLERR = %2d, POLLHUP = %2d, POLLNVAL = %2d\n", POLLERR, POLLHUP, POLLNVAL);
  printf ("POLLRDNORM = %3d, POLLRDBAND = %3d\n", POLLRDNORM, POLLRDBAND);
  printf ("POLLWRNORM = %3d, POLLWRBAND = %3d\n", POLLWRNORM, POLLWRBAND);

#ifdef __GNU__
#include <hurd/hurd_types.h>
#define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
#define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
  printf ("SELECT_READ = %3d, SELECT_WRITE = %3d, SELECT_URG= %3d\n", SELECT_READ, SELECT_WRITE, SELECT_URG);
  printf ("SELECT_ALL = %3d, SELECT_RETURNED = %3d\n", SELECT_ALL, SELECT_RETURNED);
#endif

  printf("\nPipe test\n=========\n");
  result = test_pipe();

  return result;
}

Reply to: