Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com From: "Boris Schaeling" To: Subject: modified poll() patch Date: Sat, 16 Mar 2002 14:56:37 +0100 Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0009_01C1CCFA.C5A99480" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) X-MIMEOLE: Produced By Microsoft MimeOLE V5.00.2919.6600 Importance: Normal Note-from-DJ: This may be spam ------=_NextPart_000_0009_01C1CCFA.C5A99480 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit Here is the new poll() patch. Now invalid descriptors are recognized (invalid = positive descriptors including 0 which are not open). If there are invalid descriptors poll() returns immediately with the count of invalid descriptors. The timer value is ignored. That's the way Linux handles this case. As far as I can see there is only one bug left in this poll() function: If a descriptor is closed revents is set to POLLIN and not to POLLHUP. That's the way previous poll() functions worked, too. This shouldn't be a problem as read() will return 0 and tell the application that the socket can be closed. I changed the test case, too (see polltest2.c). Hopefully this poll() doesn't cause any problems any more. Boris ------=_NextPart_000_0009_01C1CCFA.C5A99480 Content-Type: application/octet-stream; name="newpoll2.cc" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="newpoll2.cc" /* poll.cc. Implements poll(2) via usage of select(2) call.=0A= =0A= Copyright 2000, 2001 Red Hat, Inc.=0A= =0A= This file is part of Cygwin.=0A= =0A= This software is a copyrighted work licensed under the terms of the=0A= Cygwin license. Please consult the file "CYGWIN_LICENSE" for=0A= details. */=0A= =0A= #include "winsup.h"=0A= #include =0A= #include =0A= #include =0A= #include =0A= #include "security.h"=0A= #include "fhandler.h"=0A= #include "path.h"=0A= #include "dtable.h"=0A= #include "cygerrno.h"=0A= #include "cygheap.h"=0A= #include "sigproc.h"=0A= =0A= extern "C"=0A= int=0A= poll (struct pollfd *fds, unsigned int nfds, int timeout)=0A= {=0A= int max_fd =3D 0;=0A= fd_set *read_fds, *write_fds, *except_fds;=0A= struct timeval tv =3D { timeout / 1000, (timeout % 1000) * 1000 };=0A= sigframe thisframe (mainthread);=0A= =0A= for (unsigned int i =3D 0; i < nfds; ++i)=0A= if (fds[i].fd > max_fd)=0A= max_fd =3D fds[i].fd;=0A= =0A= size_t fds_size =3D howmany(max_fd + 1, NFDBITS) * sizeof (fd_mask);=0A= =0A= read_fds =3D (fd_set *) alloca (fds_size);=0A= write_fds =3D (fd_set *) alloca (fds_size);=0A= except_fds =3D (fd_set *) alloca (fds_size);=0A= =0A= if (!read_fds || !write_fds || !except_fds)=0A= {=0A= set_errno (ENOMEM);=0A= return -1;=0A= }=0A= =0A= memset (read_fds, 0, fds_size);=0A= memset (write_fds, 0, fds_size);=0A= memset (except_fds, 0, fds_size);=0A= =0A= int invalid_fds =3D 0; =0A= for (unsigned int i =3D 0; i < nfds; ++i) =0A= { =0A= fds[i].revents =3D 0; =0A= if (!cygheap->fdtab.not_open(fds[i].fd)) =0A= { =0A= if (fds[i].events & POLLIN) =0A= FD_SET(fds[i].fd, read_fds); =0A= if (fds[i].events & POLLOUT) =0A= FD_SET(fds[i].fd, write_fds); =0A= if (fds[i].events & POLLPRI) =0A= FD_SET(fds[i].fd, except_fds); =0A= } =0A= else if (fds[i].fd >=3D 0) =0A= { =0A= ++invalid_fds; =0A= fds[i].revents =3D POLLNVAL; =0A= } =0A= } =0A= =0A= if (invalid_fds) =0A= return invalid_fds; =0A= =0A= int ret =3D cygwin_select (max_fd + 1, read_fds, write_fds, = except_fds, timeout < 0 ? NULL : &tv); =0A= =0A= if (ret > 0) =0A= for (unsigned int i =3D 0; i < nfds; ++i) =0A= { =0A= if (fds[i].fd >=3D 0) =0A= { =0A= if (cygheap->fdtab.not_open(fds[i].fd)) =0A= fds[i].revents =3D POLLHUP; =0A= else =0A= { =0A= if (FD_ISSET(fds[i].fd, read_fds)) =0A= fds[i].revents |=3D POLLIN; =0A= if (FD_ISSET(fds[i].fd, write_fds)) =0A= fds[i].revents |=3D POLLOUT; =0A= if (FD_ISSET(fds[i].fd, read_fds) && FD_ISSET(fds[i].fd, = write_fds)) =0A= fds[i].revents |=3D POLLERR; =0A= if (FD_ISSET(fds[i].fd, except_fds)) =0A= fds[i].revents |=3D POLLPRI; =0A= } =0A= } =0A= } =0A= =0A= return ret; =0A= } ------=_NextPart_000_0009_01C1CCFA.C5A99480 Content-Type: application/octet-stream; name="poll.patch2" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="poll.patch2" --- poll.cc Thu Nov 15 04:25:52 2001=0A= +++ newpoll2.cc Sat Mar 16 02:06:24 2002=0A= @@ -26,7 +26,7 @@ int=0A= poll (struct pollfd *fds, unsigned int nfds, int timeout)=0A= {=0A= int max_fd =3D 0;=0A= - fd_set *open_fds, *read_fds, *write_fds, *except_fds;=0A= + fd_set *read_fds, *write_fds, *except_fds;=0A= struct timeval tv =3D { timeout / 1000, (timeout % 1000) * 1000 };=0A= sigframe thisframe (mainthread);=0A= =0A= @@ -36,63 +36,65 @@ poll (struct pollfd *fds, unsigned int n=0A= =0A= size_t fds_size =3D howmany(max_fd + 1, NFDBITS) * sizeof (fd_mask);=0A= =0A= - open_fds =3D (fd_set *) alloca (fds_size);=0A= read_fds =3D (fd_set *) alloca (fds_size);=0A= write_fds =3D (fd_set *) alloca (fds_size);=0A= except_fds =3D (fd_set *) alloca (fds_size);=0A= =0A= - if (!open_fds || !read_fds || !write_fds || !except_fds)=0A= + if (!read_fds || !write_fds || !except_fds)=0A= {=0A= set_errno (ENOMEM);=0A= return -1;=0A= }=0A= =0A= - memset (open_fds, 0, fds_size);=0A= memset (read_fds, 0, fds_size);=0A= memset (write_fds, 0, fds_size);=0A= memset (except_fds, 0, fds_size);=0A= =0A= - bool valid_fds =3D false;=0A= - for (unsigned int i =3D 0; i < nfds; ++i)=0A= - if (!cygheap->fdtab.not_open (fds[i].fd))=0A= - {=0A= - valid_fds =3D true;=0A= - fds[i].revents =3D 0;=0A= - FD_SET (fds[i].fd, open_fds);=0A= - if (fds[i].events & POLLIN)=0A= - FD_SET (fds[i].fd, read_fds);=0A= - if (fds[i].events & POLLOUT)=0A= - FD_SET (fds[i].fd, write_fds);=0A= - if (fds[i].events & POLLPRI)=0A= - FD_SET (fds[i].fd, except_fds);=0A= - }=0A= - else=0A= - fds[i].revents =3D POLLNVAL;=0A= -=0A= - int ret =3D 0;=0A= - if (valid_fds)=0A= - ret =3D cygwin_select (max_fd + 1, read_fds, write_fds, except_fds,=0A= - timeout < 0 ? NULL : &tv);=0A= -=0A= - for (unsigned int i =3D 0; i < nfds; ++i)=0A= - {=0A= - if (fds[i].revents =3D=3D POLLNVAL && ret >=3D 0)=0A= - ret++;=0A= - else if (cygheap->fdtab.not_open(fds[i].fd))=0A= - fds[i].revents =3D POLLHUP;=0A= - else if (ret < 0)=0A= - fds[i].revents =3D POLLERR;=0A= - else=0A= - {=0A= - fds[i].revents =3D 0;=0A= - if (FD_ISSET (fds[i].fd, read_fds))=0A= - fds[i].revents |=3D POLLIN;=0A= - if (FD_ISSET (fds[i].fd, write_fds))=0A= - fds[i].revents |=3D POLLOUT;=0A= - if (FD_ISSET (fds[i].fd, except_fds))=0A= - fds[i].revents |=3D POLLPRI;=0A= - }=0A= - }=0A= + int invalid_fds =3D 0; =0A= + for (unsigned int i =3D 0; i < nfds; ++i) =0A= + { =0A= + fds[i].revents =3D 0; =0A= + if (!cygheap->fdtab.not_open(fds[i].fd)) =0A= + { =0A= + if (fds[i].events & POLLIN) =0A= + FD_SET(fds[i].fd, read_fds); =0A= + if (fds[i].events & POLLOUT) =0A= + FD_SET(fds[i].fd, write_fds); =0A= + if (fds[i].events & POLLPRI) =0A= + FD_SET(fds[i].fd, except_fds); =0A= + } =0A= + else if (fds[i].fd >=3D 0) =0A= + { =0A= + ++invalid_fds; =0A= + fds[i].revents =3D POLLNVAL; =0A= + } =0A= + } =0A= +=0A= + if (invalid_fds) =0A= + return invalid_fds; =0A= +=0A= + int ret =3D cygwin_select (max_fd + 1, read_fds, write_fds, = except_fds, timeout < 0 ? NULL : &tv); =0A= +=0A= + if (ret > 0) =0A= + for (unsigned int i =3D 0; i < nfds; ++i) =0A= + { =0A= + if (fds[i].fd >=3D 0) =0A= + { =0A= + if (cygheap->fdtab.not_open(fds[i].fd)) =0A= + fds[i].revents =3D POLLHUP; =0A= + else =0A= + { =0A= + if (FD_ISSET(fds[i].fd, read_fds)) =0A= + fds[i].revents |=3D POLLIN; =0A= + if (FD_ISSET(fds[i].fd, write_fds)) =0A= + fds[i].revents |=3D POLLOUT; =0A= + if (FD_ISSET(fds[i].fd, read_fds) && = FD_ISSET(fds[i].fd, write_fds)) =0A= + fds[i].revents |=3D POLLERR; =0A= + if (FD_ISSET(fds[i].fd, except_fds)) =0A= + fds[i].revents |=3D POLLPRI; =0A= + } =0A= + } =0A= + } =0A= =0A= - return ret;=0A= -}=0A= + return ret; =0A= +} =0A= \ No newline at end of file=0A= ------=_NextPart_000_0009_01C1CCFA.C5A99480 Content-Type: application/octet-stream; name="polltest2.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="polltest2.c" /* gcc -opolltest2 polltest2.c */=20 #include =20 #include =20 #include =20 #include =20 #include =20 void callback_alarm(int sig) { return; }=20 int main()=20 {=20 struct pollfd p[3];=20 memset(p, 0, sizeof(struct pollfd) * 3);=20 p[0].fd =3D -1;=20 p[1].fd =3D -1;=20 p[2].fd =3D -1;=20 printf("all descriptors are negative - poll() must wait for 2 = seconds\n");=20 poll(p, 3, 2000);=20 printf("all descriptors are negative - revents for any descriptor must = be 0: %d, %d, %d\n", p[0].revents, p[1].revents, p[2].revents);=20 p[2].fd =3D 0;=20 printf("no descriptor is ready - poll() must return 0: %d\n", poll(p, = 3, 500));=20 printf("no descriptor is ready - revents for any descriptor must be 0: = %d, %d, %d\n", p[0].revents, p[1].revents, p[2].revents);=20 signal(SIGALRM, callback_alarm);=20 alarm(1);=20 printf("SIGALRM - poll() must return -1: %d\n", poll(p, 3, 1500));=20 printf("SIGALRM - revents for any descriptor must be 0: %d, %d, %d\n", = p[0].revents, p[1].revents, p[2].revents);=20 p[1].fd =3D 1000;=20 p[2].fd =3D 1001;=20 printf("2 descriptors are invalid - poll() must return 2 immediately: = %d\n", poll(p, 3, 10000));=20 printf("2 descriptors are invalid - revents must be POLLNVAL for 2. and = 3. descriptor: %d, %d, %d\n", p[0].revents, p[1].revents, p[2].revents); = } ------=_NextPart_000_0009_01C1CCFA.C5A99480 Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ ------=_NextPart_000_0009_01C1CCFA.C5A99480--