This is the mail archive of the
libc-alpha@cygnus.com
mailing list for the glibc project.
Re: poll emulation
- To: james@and.org
- Subject: Re: poll emulation
- From: Andreas Jaeger <aj@arthur.rhein-neckar.de>
- Date: 18 Apr 1999 14:55:49 +0200
- Cc: libc-alpha@cygnus.com
- Mail-Copies-To: never
- References: <nnbthu2v7g.fsf@hoth.vader.org>
>>>>> 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