Subject: Re: pkg/30129
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: John D. Baker <jdbaker@mylinuxisp.com>
List: pkgsrc-bugs
Date: 05/05/2005 20:23:01
The following reply was made to PR pkg/30129; it has been noted by GNATS.

From: "John D. Baker" <jdbaker@mylinuxisp.com>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: pkg/30129
Date: Thu, 5 May 2005 15:23:02 -0500 (CDT)

 Trials with "http://sealiesoftware.com/fakepoll.h" are promising.
 On my system, I put it in "/usr/local/include/sys/fakepoll.h" and
 point affected source files to it explicitly.  I.e.:
 
     /* #include <sys/poll.h> */
     #include "/usr/local/include/sys/fakepoll.h"
 
 If 'errno.h' is also included, it must preceed the inclusion of
 'fakepoll.h'.
 
 The compiler seems to ignore the 'inline' directive, placing the
 code in the general text segment of the object module.  This causes
 the linker to fail, complaining about multiple definitions of _poll.
 
 I've split 'fakepoll.h' in two, with just the definitions in 'fakepoll.h'
 proper, and the code for poll() in 'fakepoll_impl.h'.  The idea is that
 only one module need include 'fakepoll_impl.h' and the rest just include
 'fakepoll.h'.
 
 The initial examples are:
 
     work/arts-1.4.0/flow/gsl/gslcommon.c  (fakepoll_impl.h)
     work/arts-1.4.0/flow/gsl/gslopmaster.c  (fakepoll.h)
 
 So far, this has worked, but I have hit what appears to be a compiler-
 or assembler-related problem probably not related to the issue of this
 PR.
 
 -------------------------------------
 
 // fakepoll.h
 // poll using select
 // Warning: a call to this poll() takes about 4K of stack space.
 
 // Greg Parker     gparker-web@sealiesoftware.com     December 2000
 // This code is in the public domain and may be copied or modified without
 // permission.
 
 // Updated May 2002:
 // * fix crash when an fd is less than 0
 // * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
 // * don't set POLLIN or POLLOUT in revents if it wasn't requested
 //   in events (only happens when an fd is in the poll set twice)
 
 #ifndef _FAKE_POLL_H
 #define _FAKE_POLL_H
 
 #include <limits.h>
 #define FD_SETSIZE OPEN_MAX
 #include <sys/types.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <stdlib.h>
 
 typedef struct pollfd {
     int fd;                         /* file desc to poll */
     short events;                   /* events of interest on fd */
     short revents;                  /* events that occurred on fd */
 } pollfd_t;
 
 
 // poll flags
 #define POLLIN  0x0001
 #define POLLOUT 0x0004
 #define POLLERR 0x0008
 
 // synonyms
 #define POLLNORM POLLIN
 #define POLLPRI POLLIN
 #define POLLRDNORM POLLIN
 #define POLLRDBAND POLLIN
 #define POLLWRNORM POLLOUT
 #define POLLWRBAND POLLOUT
 
 // ignored
 #define POLLHUP 0x0010
 #define POLLNVAL 0x0020
 
 
 #endif
 
 --------------------------------------------------------
 
 // fakepoll_impl.h
 // poll using select
 // Warning: a call to this poll() takes about 4K of stack space.
 
 // Greg Parker     gparker-web@sealiesoftware.com     December 2000
 // This code is in the public domain and may be copied or modified without
 // permission.
 
 // Updated May 2002:
 // * fix crash when an fd is less than 0
 // * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
 // * don't set POLLIN or POLLOUT in revents if it wasn't requested
 //   in events (only happens when an fd is in the poll set twice)
 
 #ifndef _FAKE_POLL_IMPL_H
 #define _FAKE_POLL_IMPL_H
 
 #include "/usr/local/include/sys/fakepoll.h"
 
 inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
 {
     struct timeval tv;
     struct timeval *tvp;
     fd_set readFDs, writeFDs, exceptFDs;
     fd_set *readp, *writep, *exceptp;
     struct pollfd *pollEnd, *p;
     int selected;
     int result;
     int maxFD;
 
     if (!pollSet) {
         pollEnd = NULL;
         readp = NULL;
         writep = NULL;
         exceptp = NULL;
         maxFD = 0;
     }
     else {
         pollEnd = pollSet + pollCount;
         readp = &readFDs;
         writep = &writeFDs;
         exceptp = &exceptFDs;
 
         FD_ZERO(readp);
         FD_ZERO(writep);
         FD_ZERO(exceptp);
 
         // Find the biggest fd in the poll set
         maxFD = 0;
         for (p = pollSet; p < pollEnd; p++) {
             if (p->fd > maxFD) maxFD = p->fd;
         }
 
         if (maxFD >= FD_SETSIZE) {
             // At least one fd is too big
             errno = EINVAL;
             return -1;
         }
 
         // Transcribe flags from the poll set to the fd sets
         for (p = pollSet; p < pollEnd; p++) {
             if (p->fd < 0) {
                 // Negative fd checks nothing and always reports zero
             } else {
                 if (p->events & POLLIN)  FD_SET(p->fd, readp);
                 if (p->events & POLLOUT) FD_SET(p->fd, writep);
                 if (p->events != 0)      FD_SET(p->fd, exceptp);
                 // POLLERR is never set coming in; poll() always reports errors
                 // But don't report if we're not listening to anything at all.
             }
         }
     }
 
     // poll timeout is in milliseconds. Convert to struct timeval.
     // poll timeout == -1 : wait forever : select timeout of NULL
     // poll timeout == 0  : return immediately : select timeout of zero
     if (pollTimeout >= 0) {
         tv.tv_sec = pollTimeout / 1000;
         tv.tv_usec = (pollTimeout % 1000) * 1000;
         tvp = &tv;
     } else {
         tvp = NULL;
     }
 
 
     selected = select(maxFD+1, readp, writep, exceptp, tvp);
 
 
     if (selected < 0) {
         // Error during select
         result = -1;
     }
     else if (selected > 0) {
         // Select found something
         // Transcribe result from fd sets to poll set.
         // Also count the number of selected fds. poll returns the
         // number of ready fds; select returns the number of bits set.
         int polled = 0;
         for (p = pollSet; p < pollEnd; p++) {
             p->revents = 0;
             if (p->fd < 0) {
                 // Negative fd always reports zero
             } else {
                 if ((p->events & POLLIN)   &&  FD_ISSET(p->fd, readp)) {
                     p->revents |= POLLIN;
                 }
                 if ((p->events & POLLOUT)  &&  FD_ISSET(p->fd, writep)) {
                     p->revents |= POLLOUT;
                 }
                 if ((p->events != 0)       &&  FD_ISSET(p->fd, exceptp)) {
                     p->revents |= POLLERR;
                 }
 
                 if (p->revents) polled++;
             }
         }
         result = polled;
     }
     else {
         // selected == 0, select timed out before anything happened
         // Clear all result bits and return zero.
         for (p = pollSet; p < pollEnd; p++) {
             p->revents = 0;
         }
         result = 0;
     }
 
     return result;
 }
 
 
 #endif
 
 -----------------------------------
 
 -- 
 John D. Baker, KN5UKS                    NetBSD     Darwin/MacOS X
 jdbaker(at)mylinuxisp(dot)com                 OpenBSD            FreeBSD
 BSD -- It just sits there and _works_!