public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* modified poll() patch
@ 2002-03-16 10:47 Boris Schaeling
  2002-03-19  3:16 ` Corinna Vinschen
  0 siblings, 1 reply; 5+ messages in thread
From: Boris Schaeling @ 2002-03-16 10:47 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 722 bytes --]

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

[-- Attachment #2: newpoll2.cc --]
[-- Type: application/octet-stream, Size: 2801 bytes --]

/* poll.cc. Implements poll(2) via usage of select(2) call.

   Copyright 2000, 2001 Red Hat, Inc.

   This file is part of Cygwin.

   This software is a copyrighted work licensed under the terms of the
   Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
   details. */

#include "winsup.h"
#include <sys/time.h>
#include <sys/poll.h>
#include <errno.h>
#include <stdlib.h>
#include "security.h"
#include "fhandler.h"
#include "path.h"
#include "dtable.h"
#include "cygerrno.h"
#include "cygheap.h"
#include "sigproc.h"

extern "C"
int
poll (struct pollfd *fds, unsigned int nfds, int timeout)
{
  int max_fd = 0;
  fd_set *read_fds, *write_fds, *except_fds;
  struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
  sigframe thisframe (mainthread);

  for (unsigned int i = 0; i < nfds; ++i)
    if (fds[i].fd > max_fd)
      max_fd = fds[i].fd;

  size_t fds_size = howmany(max_fd + 1, NFDBITS) * sizeof (fd_mask);

  read_fds = (fd_set *) alloca (fds_size);
  write_fds = (fd_set *) alloca (fds_size);
  except_fds = (fd_set *) alloca (fds_size);

  if (!read_fds || !write_fds || !except_fds)
    {
      set_errno (ENOMEM);
      return -1;
    }

  memset (read_fds, 0, fds_size);
  memset (write_fds, 0, fds_size);
  memset (except_fds, 0, fds_size);

  int invalid_fds = 0; 
  for (unsigned int i = 0; i < nfds; ++i) 
    { 
      fds[i].revents = 0; 
      if (!cygheap->fdtab.not_open(fds[i].fd)) 
        { 
          if (fds[i].events & POLLIN) 
            FD_SET(fds[i].fd, read_fds); 
          if (fds[i].events & POLLOUT) 
            FD_SET(fds[i].fd, write_fds); 
          if (fds[i].events & POLLPRI) 
            FD_SET(fds[i].fd, except_fds); 
        } 
      else if (fds[i].fd >= 0) 
        { 
          ++invalid_fds; 
          fds[i].revents = POLLNVAL; 
        } 
    } 

  if (invalid_fds) 
    return invalid_fds; 

  int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, timeout < 0 ? NULL : &tv); 

  if (ret > 0) 
    for (unsigned int i = 0; i < nfds; ++i) 
      { 
        if (fds[i].fd >= 0) 
          { 
            if (cygheap->fdtab.not_open(fds[i].fd)) 
              fds[i].revents = POLLHUP; 
            else 
              { 
                if (FD_ISSET(fds[i].fd, read_fds)) 
                  fds[i].revents |= POLLIN; 
                if (FD_ISSET(fds[i].fd, write_fds)) 
                  fds[i].revents |= POLLOUT; 
                if (FD_ISSET(fds[i].fd, read_fds) && FD_ISSET(fds[i].fd, write_fds)) 
                  fds[i].revents |= POLLERR; 
                if (FD_ISSET(fds[i].fd, except_fds)) 
                  fds[i].revents |= POLLPRI; 
              } 
          } 
      } 

  return ret; 
} 

[-- Attachment #3: poll.patch2 --]
[-- Type: application/octet-stream, Size: 3759 bytes --]

--- poll.cc	Thu Nov 15 04:25:52 2001
+++ newpoll2.cc	Sat Mar 16 02:06:24 2002
@@ -26,7 +26,7 @@ int
 poll (struct pollfd *fds, unsigned int nfds, int timeout)
 {
   int max_fd = 0;
-  fd_set *open_fds, *read_fds, *write_fds, *except_fds;
+  fd_set *read_fds, *write_fds, *except_fds;
   struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
   sigframe thisframe (mainthread);
 
@@ -36,63 +36,65 @@ poll (struct pollfd *fds, unsigned int n
 
   size_t fds_size = howmany(max_fd + 1, NFDBITS) * sizeof (fd_mask);
 
-  open_fds = (fd_set *) alloca (fds_size);
   read_fds = (fd_set *) alloca (fds_size);
   write_fds = (fd_set *) alloca (fds_size);
   except_fds = (fd_set *) alloca (fds_size);
 
-  if (!open_fds || !read_fds || !write_fds || !except_fds)
+  if (!read_fds || !write_fds || !except_fds)
     {
       set_errno (ENOMEM);
       return -1;
     }
 
-  memset (open_fds, 0, fds_size);
   memset (read_fds, 0, fds_size);
   memset (write_fds, 0, fds_size);
   memset (except_fds, 0, fds_size);
 
-  bool valid_fds = false;
-  for (unsigned int i = 0; i < nfds; ++i)
-    if (!cygheap->fdtab.not_open (fds[i].fd))
-      {
-	valid_fds = true;
-	fds[i].revents = 0;
-	FD_SET (fds[i].fd, open_fds);
-	if (fds[i].events & POLLIN)
-	  FD_SET (fds[i].fd, read_fds);
-	if (fds[i].events & POLLOUT)
-	  FD_SET (fds[i].fd, write_fds);
-	if (fds[i].events & POLLPRI)
-	  FD_SET (fds[i].fd, except_fds);
-      }
-      else
-	fds[i].revents = POLLNVAL;
-
-  int ret = 0;
-  if (valid_fds)
-    ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds,
-			 timeout < 0 ? NULL : &tv);
-
-  for (unsigned int i = 0; i < nfds; ++i)
-    {
-      if (fds[i].revents == POLLNVAL && ret >= 0)
-	ret++;
-      else if (cygheap->fdtab.not_open(fds[i].fd))
-	fds[i].revents = POLLHUP;
-      else if (ret < 0)
-	fds[i].revents = POLLERR;
-      else
-	{
-	  fds[i].revents = 0;
-	  if (FD_ISSET (fds[i].fd, read_fds))
-	    fds[i].revents |= POLLIN;
-	  if (FD_ISSET (fds[i].fd, write_fds))
-	    fds[i].revents |= POLLOUT;
-	  if (FD_ISSET (fds[i].fd, except_fds))
-	    fds[i].revents |= POLLPRI;
-	}
-    }
+  int invalid_fds = 0; 
+  for (unsigned int i = 0; i < nfds; ++i) 
+    { 
+      fds[i].revents = 0; 
+      if (!cygheap->fdtab.not_open(fds[i].fd)) 
+        { 
+          if (fds[i].events & POLLIN) 
+            FD_SET(fds[i].fd, read_fds); 
+          if (fds[i].events & POLLOUT) 
+            FD_SET(fds[i].fd, write_fds); 
+          if (fds[i].events & POLLPRI) 
+            FD_SET(fds[i].fd, except_fds); 
+        } 
+      else if (fds[i].fd >= 0) 
+        { 
+          ++invalid_fds; 
+          fds[i].revents = POLLNVAL; 
+        } 
+    } 
+
+  if (invalid_fds) 
+    return invalid_fds; 
+
+  int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, timeout < 0 ? NULL : &tv); 
+
+  if (ret > 0) 
+    for (unsigned int i = 0; i < nfds; ++i) 
+      { 
+        if (fds[i].fd >= 0) 
+          { 
+            if (cygheap->fdtab.not_open(fds[i].fd)) 
+              fds[i].revents = POLLHUP; 
+            else 
+              { 
+                if (FD_ISSET(fds[i].fd, read_fds)) 
+                  fds[i].revents |= POLLIN; 
+                if (FD_ISSET(fds[i].fd, write_fds)) 
+                  fds[i].revents |= POLLOUT; 
+                if (FD_ISSET(fds[i].fd, read_fds) && FD_ISSET(fds[i].fd, write_fds)) 
+                  fds[i].revents |= POLLERR; 
+                if (FD_ISSET(fds[i].fd, except_fds)) 
+                  fds[i].revents |= POLLPRI; 
+              } 
+          } 
+      } 
 
-  return ret;
-}
+  return ret; 
+} 
\ No newline at end of file

[-- Attachment #4: polltest2.c --]
[-- Type: application/octet-stream, Size: 1336 bytes --]

/* gcc -opolltest2 polltest2.c */ 

#include <stdio.h> 
#include <string.h> 
#include <poll.h> 
#include <signal.h> 
#include <unistd.h> 

void callback_alarm(int sig) { return; } 

int main() 
{ 
	struct pollfd p[3]; 

	memset(p, 0, sizeof(struct pollfd) * 3); 

	p[0].fd = -1; 
	p[1].fd = -1; 
	p[2].fd = -1; 

	printf("all descriptors are negative - poll() must wait for 2 seconds\n"); 
	poll(p, 3, 2000); 
	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); 

	p[2].fd = 0; 
	printf("no descriptor is ready - poll() must return 0: %d\n", poll(p, 3, 500)); 
	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); 

	signal(SIGALRM, callback_alarm); 

	alarm(1); 

	printf("SIGALRM - poll() must return -1: %d\n", poll(p, 3, 1500)); 
	printf("SIGALRM - revents for any descriptor must be 0: %d, %d, %d\n", p[0].revents, p[1].revents, p[2].revents); 

	p[1].fd = 1000; 
	p[2].fd = 1001; 
	printf("2 descriptors are invalid - poll() must return 2 immediately: %d\n", poll(p, 3, 10000)); 
	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); 
}

[-- Attachment #5: Type: text/plain, Size: 214 bytes --]

--
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/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: modified poll() patch
  2002-03-16 10:47 modified poll() patch Boris Schaeling
@ 2002-03-19  3:16 ` Corinna Vinschen
  2002-03-19  5:15   ` AW: " Boris Schaeling
  0 siblings, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2002-03-19  3:16 UTC (permalink / raw)
  To: cygwin

On Sat, Mar 16, 2002 at 02:56:37PM +0100, Boris Schaeling wrote:
> Here is the new poll() patch. Now invalid descriptors are recognized

Boris,

thanks for the patch but could you please send a diff related to
the latest from current cvs?  I didn't back out your patch since
I'd waited for your correction.  This means, I can't apply your
patch cleanly.

Please send the new patch file and a ChangeLog entry (you know the
rules) briefly describing just the changes since your previous version.

Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                                mailto:cygwin@cygwin.com
Red Hat, Inc.

--
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/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* AW: modified poll() patch
  2002-03-19  3:16 ` Corinna Vinschen
@ 2002-03-19  5:15   ` Boris Schaeling
  2002-03-19  9:27     ` Corinna Vinschen
  0 siblings, 1 reply; 5+ messages in thread
From: Boris Schaeling @ 2002-03-19  5:15 UTC (permalink / raw)
  To: Corinna Vinschen

[-- Attachment #1: Type: text/plain, Size: 439 bytes --]



> -----Ursprüngliche Nachricht-----
> Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com]Im Auftrag
> von Corinna Vinschen
> Gesendet: Dienstag, 19. März 2002 11:55
> An: cygwin@cygwin.com
> Betreff: Re: modified poll() patch

> [...]
> thanks for the patch but could you please send a diff related to
> the latest from current cvs?  I didn't back out your patch since

Hi Corinna,

I've attached patch and changelog.

Boris

[-- Attachment #2: change.log2 --]
[-- Type: application/octet-stream, Size: 173 bytes --]

2002-03-19  Boris Schaeling  <boriss@web.de> 

	* poll.cc: add support for invalid descriptors 
	(invalid means positive descriptors including 0 
	which are not open) 

[-- Attachment #3: poll.patch2 --]
[-- Type: application/octet-stream, Size: 2620 bytes --]

--- poll.cc	Tue Mar 19 13:23:26 2002
+++ newpoll2.cc	Sat Mar 16 02:06:24 2002
@@ -50,41 +50,51 @@ poll (struct pollfd *fds, unsigned int n
   memset (write_fds, 0, fds_size);
   memset (except_fds, 0, fds_size);
 
+  int invalid_fds = 0; 
   for (unsigned int i = 0; i < nfds; ++i) 
     { 
       fds[i].revents = 0; 
       if (!cygheap->fdtab.not_open(fds[i].fd)) 
-	{ 
-	  if (fds[i].events & POLLIN) 
-	    FD_SET(fds[i].fd, read_fds); 
-	  if (fds[i].events & POLLOUT) 
-	    FD_SET(fds[i].fd, write_fds); 
-	  if (fds[i].events & POLLPRI) 
-	    FD_SET(fds[i].fd, except_fds); 
-	} 
+        { 
+          if (fds[i].events & POLLIN) 
+            FD_SET(fds[i].fd, read_fds); 
+          if (fds[i].events & POLLOUT) 
+            FD_SET(fds[i].fd, write_fds); 
+          if (fds[i].events & POLLPRI) 
+            FD_SET(fds[i].fd, except_fds); 
+        } 
+      else if (fds[i].fd >= 0) 
+        { 
+          ++invalid_fds; 
+          fds[i].revents = POLLNVAL; 
+        } 
     } 
 
-  int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, timeout < 0 ? NULL : &tv);
+  if (invalid_fds) 
+    return invalid_fds; 
+
+  int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, timeout < 0 ? NULL : &tv); 
 
   if (ret > 0) 
     for (unsigned int i = 0; i < nfds; ++i) 
       { 
-	if (fds[i].fd < 0) 
-	  fds[i].revents = POLLNVAL; 
-	else if (cygheap->fdtab.not_open(fds[i].fd)) 
-	  fds[i].revents = POLLHUP; 
-	else 
-	  { 
-	    if (FD_ISSET(fds[i].fd, read_fds)) 
-	      fds[i].revents |= POLLIN; 
-	    if (FD_ISSET(fds[i].fd, write_fds)) 
-	      fds[i].revents |= POLLOUT; 
-	    if (FD_ISSET(fds[i].fd, read_fds) && FD_ISSET(fds[i].fd, write_fds)) 
-	      fds[i].revents |= POLLERR; 
-	    if (FD_ISSET(fds[i].fd, except_fds)) 
-	      fds[i].revents |= POLLPRI; 
-	  } 
+        if (fds[i].fd >= 0) 
+          { 
+            if (cygheap->fdtab.not_open(fds[i].fd)) 
+              fds[i].revents = POLLHUP; 
+            else 
+              { 
+                if (FD_ISSET(fds[i].fd, read_fds)) 
+                  fds[i].revents |= POLLIN; 
+                if (FD_ISSET(fds[i].fd, write_fds)) 
+                  fds[i].revents |= POLLOUT; 
+                if (FD_ISSET(fds[i].fd, read_fds) && FD_ISSET(fds[i].fd, write_fds)) 
+                  fds[i].revents |= POLLERR; 
+                if (FD_ISSET(fds[i].fd, except_fds)) 
+                  fds[i].revents |= POLLPRI; 
+              } 
+          } 
       } 
 
   return ret; 
-} 
+} 
\ No newline at end of file


[-- Attachment #4: Type: text/plain, Size: 214 bytes --]

--
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/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: modified poll() patch
  2002-03-19  5:15   ` AW: " Boris Schaeling
@ 2002-03-19  9:27     ` Corinna Vinschen
  2002-03-21  5:43       ` Jason Tishler
  0 siblings, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2002-03-19  9:27 UTC (permalink / raw)
  To: cygwin

On Tue, Mar 19, 2002 at 01:35:51PM +0100, Boris Schaeling wrote:
> 
> 
> > -----Ursprüngliche Nachricht-----
> > Von: cygwin-owner@cygwin.com [mailto:cygwin-owner@cygwin.com]Im Auftrag
> > von Corinna Vinschen
> > Gesendet: Dienstag, 19. März 2002 11:55
> > An: cygwin@cygwin.com
> > Betreff: Re: modified poll() patch
> 
> > [...]
> > thanks for the patch but could you please send a diff related to
> > the latest from current cvs?  I didn't back out your patch since
> 
> Hi Corinna,
> 
> I've attached patch and changelog.

Thanks, applied.  I had to change the ChangeLog, though...

Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                                mailto:cygwin@cygwin.com
Red Hat, Inc.

--
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/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: modified poll() patch
  2002-03-19  9:27     ` Corinna Vinschen
@ 2002-03-21  5:43       ` Jason Tishler
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Tishler @ 2002-03-21  5:43 UTC (permalink / raw)
  To: cygwin

Boris,

On Tue, Mar 19, 2002 at 06:14:13PM +0100, Corinna Vinschen wrote:
> On Tue, Mar 19, 2002 at 01:35:51PM +0100, Boris Schaeling wrote:
> > > thanks for the patch but could you please send a diff related to
> > > the latest from current cvs?  I didn't back out your patch since
> > 
> > I've attached patch and changelog.
> 
> Thanks, applied.  I had to change the ChangeLog, though...

I just checked that poll() in the latest snapshot does not hang.  Thanks
for making this change.

Jason

--
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/

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-03-21 13:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-16 10:47 modified poll() patch Boris Schaeling
2002-03-19  3:16 ` Corinna Vinschen
2002-03-19  5:15   ` AW: " Boris Schaeling
2002-03-19  9:27     ` Corinna Vinschen
2002-03-21  5:43       ` Jason Tishler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).