This is the mail archive of the libc-alpha@cygnus.com 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]

Re: poll emulation


>>>>> James Antill writes:

James>  I'm working on a program that needs to be able to run on 2.0.x and
James> 2.2.x kernels so although I'm using poll internally I need the
James> emulation to work as full as possible.
James>  At the moment everything fails if you have an fd in your poll set
James> that is invalid (select return -1 and sets errno == EBADF, where poll
James> will just set a flag in the poll structure for that fd).
James>  So here is an addition to the poll emulation inside glibc, this was
James> written as an add on to glibc-2.0.x so I'll have to do a little more
James> work to generate a patch against 2.1.x but you'll get the idea and
James> hopefully someone will be able to tell me it will go in/it'll never go 
James> in.

Sorry for the late answer.

Ulrich just checked the appended patch in which is different than your
patch but should fix the problem.  Could you test it and tell us if
you encounter problems with it?  The patch is against glibc 2.1.

Thanks,
Andreas

1999-04-18  Ulrich Drepper  <drepper@cygnus.com>

        * sysdeps/unix/bsd/poll.c (__poll): Add more compatiblity code to
        detect and handle invalid descriptors.



Index: sysdeps/unix/bsd/poll.c
===================================================================
--- sysdeps/unix/bsd/poll.c	1998/11/18 14:11:58	1.7
+++ sysdeps/unix/bsd/poll.c	1999/04/18 01:17:51	1.9
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -60,52 +60,125 @@
   __bzero (xset, bytes);
 
   for (f = fds; f < &fds[nfds]; ++f)
-    if (f->fd >= 0)
-      {
-	if (f->fd >= max_fd_size)
-	  {
-	    /* The user provides a file descriptor number which is higher
-	       than the maximum we got from the `getdtablesize' call.
-	       Maybe this is ok so enlarge the arrays.  */
-	    fd_set *nrset, *nwset, *nxset;
-	    int nbytes;
-
-	    max_fd_size = roundup (f->fd, __NFDBITS);
-	    nbytes = howmany (max_fd_size, __NFDBITS);
-
-	    nrset = alloca (nbytes);
-	    nwset = alloca (nbytes);
-	    nxset = alloca (nbytes);
-
-	    __bzero ((char *) nrset + bytes, nbytes - bytes);
-	    __bzero ((char *) nwset + bytes, nbytes - bytes);
-	    __bzero ((char *) nxset + bytes, nbytes - bytes);
-
-	    rset = memcpy (nrset, rset, bytes);
-	    wset = memcpy (nwset, wset, bytes);
-	    xset = memcpy (nxset, xset, bytes);
-
-	    bytes = nbytes;
-	  }
-
-	if (f->events & POLLIN)
-	  FD_SET (f->fd, rset);
-	if (f->events & POLLOUT)
-	  FD_SET (f->fd, wset);
-	if (f->events & POLLPRI)
-	  FD_SET (f->fd, xset);
-	if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
-	  maxfd = f->fd;
-      }
+    {
+      f->revents = 0;
+      if (f->fd >= 0)
+	{
+	  if (f->fd >= max_fd_size)
+	    {
+	      /* The user provides a file descriptor number which is higher
+		 than the maximum we got from the `getdtablesize' call.
+		 Maybe this is ok so enlarge the arrays.  */
+	      fd_set *nrset, *nwset, *nxset;
+	      int nbytes;
+
+	      max_fd_size = roundup (f->fd, __NFDBITS);
+	      nbytes = howmany (max_fd_size, __NFDBITS);
+
+	      nrset = alloca (nbytes);
+	      nwset = alloca (nbytes);
+	      nxset = alloca (nbytes);
+
+	      __bzero ((char *) nrset + bytes, nbytes - bytes);
+	      __bzero ((char *) nwset + bytes, nbytes - bytes);
+	      __bzero ((char *) nxset + bytes, nbytes - bytes);
+
+	      rset = memcpy (nrset, rset, bytes);
+	      wset = memcpy (nwset, wset, bytes);
+	      xset = memcpy (nxset, xset, bytes);
+
+	      bytes = nbytes;
+	    }
+
+	  if (f->events & POLLIN)
+	    FD_SET (f->fd, rset);
+	  if (f->events & POLLOUT)
+	    FD_SET (f->fd, wset);
+	  if (f->events & POLLPRI)
+	    FD_SET (f->fd, xset);
+	  if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
+	    maxfd = f->fd;
+	}
+    }
 
   tv.tv_sec = timeout / 1000;
   tv.tv_usec = (timeout % 1000) * 1000;
+
+  while (1)
+    {
+      ready = __select (maxfd + 1, rset, wset, xset,
+			timeout == -1 ? NULL : &tv);
+
+      /* It might be that one or more of the file descriptors is invalid.
+	 We now try to find and mark them and then try again.  */
+      if (ready == -1 && errno == EBADF)
+	{
+	  fd_set *sngl_rset = alloca (bytes);
+	  fd_set *sngl_wset = alloca (bytes);
+	  fd_set *sngl_xset = alloca (bytes);
+	  struct timeval sngl_tv;
+
+	  /* Clear the original set.  */
+	  __bzero (rset, bytes);
+	  __bzero (wset, bytes);
+	  __bzero (xset, bytes);
+
+	  /* This means we don't wait for input.  */
+	  sngl_tv.tv_sec = 0;
+	  sngl_tv.tv_usec = 0;
+
+	  maxfd = -1;
+
+	  /* Reset the return value.  */
+	  ready = 0;
+
+	  for (f = fds; f < &fds[nfds]; ++f)
+	    if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
+		&& (f->revents & POLLNVAL) == 0)
+	      {
+		int n;
+
+		__bzero (sngl_rset, bytes);
+		__bzero (sngl_wset, bytes);
+		__bzero (sngl_xset, bytes);
+
+		if (f->events & POLLIN)
+		  FD_SET (f->fd, sngl_rset);
+		if (f->events & POLLOUT)
+		  FD_SET (f->fd, sngl_wset);
+		if (f->events & POLLPRI)
+		  FD_SET (f->fd, sngl_xset);
+
+		n = __select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
+			      &sngl_tv);
+		if (n != -1)
+		  {
+		    /* This descriptor is ok.  */
+		    if (f->events & POLLIN)
+		      FD_SET (f->fd, rset);
+		    if (f->events & POLLOUT)
+		      FD_SET (f->fd, wset);
+		    if (f->events & POLLPRI)
+		      FD_SET (f->fd, xset);
+		    if (f->fd > maxfd)
+		      maxfd = f->fd;
+		    if (n > 0)
+		      /* Count it as being available.  */
+		      ++ready;
+		  }
+		else if (errno == EBADF)
+		  f->revents |= POLLNVAL;
+	      }
+	  /* Try again.  */
+	  continue;
+	}
+
+      break;
+    }
 
-  ready = __select (maxfd + 1, rset, wset, xset, timeout == -1 ? NULL : &tv);
   if (ready > 0)
     for (f = fds; f < &fds[nfds]; ++f)
       {
-	f->revents = 0;
 	if (f->fd >= 0)
 	  {
 	    if (FD_ISSET (f->fd, rset))

-- 
 Andreas Jaeger   aj@arthur.rhein-neckar.de    jaeger@informatik.uni-kl.de
  for pgp-key finger ajaeger@aixd1.rhrk.uni-kl.de


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