about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--sunrpc/rpc_cout.c2
-rw-r--r--sysdeps/unix/bsd/poll.c150
3 files changed, 116 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog
index a8a7d5d754..dff9614c98 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+1999-04-18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/bsd/poll.c (__poll): Add more compatiblity code to
+	detect and handle invalid descriptors.
+
 1999-04-17  Thorsten Kukuk  <kukuk@suse.de>
 
 	* timezone/zic.c (dolink): Append complete path ot only filename
diff --git a/sunrpc/rpc_cout.c b/sunrpc/rpc_cout.c
index 2d8e69ea75..a8471cacc9 100644
--- a/sunrpc/rpc_cout.c
+++ b/sunrpc/rpc_cout.c
@@ -175,7 +175,7 @@ print_header (const definition * def)
   if (inlineflag == 0)
     return;
   /*May cause lint to complain. but  ... */
-  f_print (fout, "\t register int32_t *buf;\n\n");
+  f_print (fout, "\tregister int32_t *buf;\n\n");
 }
 
 static void
diff --git a/sysdeps/unix/bsd/poll.c b/sysdeps/unix/bsd/poll.c
index 7fb4fcc3fa..5f65e76122 100644
--- a/sysdeps/unix/bsd/poll.c
+++ b/sysdeps/unix/bsd/poll.c
@@ -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,122 @@ __poll (fds, nfds, timeout)
   __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;
 
-  ready = __select (maxfd + 1, rset, wset, xset, timeout == -1 ? NULL : &tv);
+  do
+    {
+      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;
+	      }
+	}
+    }
+  while (ready == 0);
+
   if (ready > 0)
     for (f = fds; f < &fds[nfds]; ++f)
       {
-	f->revents = 0;
 	if (f->fd >= 0)
 	  {
 	    if (FD_ISSET (f->fd, rset))