This is the mail archive of the cygwin-developers@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [tolj@wapme-systems.de: Re: Problem with accept?!!


Thomas,

On Tue, Jun 03, 2003 at 02:01:15PM +0200, Corinna Vinschen wrote:
> FYI, I've just switch accept() to use cygwin_select instead of its own
> thread.  Works like a charm.  fhandler_socket::accept looks like this:
> [...]

I have a complete new implementation now, using cygwin_select.  It seems
to work really nicely.  However, would you mind to have a look into this
before I check it in?  Again, all my tests are working fine, this time
even the message when trying to connect an already connected socket makes
sense :-)

I've attached the patch related to current CVS.  Note that I've moved
the cygwin_select stuff into cygwin_connect and cygwin_accept in net.cc
since there's the natural point at which the file descriptor is still
accessible (instead of propagating the descriptor to the fhandler_socket
method).

Corinna

	* fhandler_socket.cc (connect_thread): Remove.
	(accept_thread): Remove.
	(fhandler_socket::connect): Remove all special blocking handling.
	(fhandler_socket::accept): Ditto.
	* net.cc (cygwin_connect): Make blocking sockets temporarily
	non-blocking and call cygwin_select on them to be interruptible.
	(cygwin_accept):  Ditto.

Index: fhandler_socket.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_socket.cc,v
retrieving revision 1.102
diff -u -p -r1.102 fhandler_socket.cc
--- fhandler_socket.cc	2 Jun 2003 21:20:22 -0000	1.102
+++ fhandler_socket.cc	3 Jun 2003 12:43:04 -0000
@@ -33,6 +33,7 @@
 #include "sigproc.h"
 #include "wsock_event.h"
 #include "cygthread.h"
+#include "select.h"
 #include <unistd.h>
 
 #define ENTROPY_SOURCE_DEV_UNIT 9
@@ -120,30 +121,6 @@ get_inet_addr (const struct sockaddr *in
     }
 }
 
-struct sock_thread_data
-{
-  int socket;
-  sockaddr *peer;
-  int *len;
-  int ret;
-};
-
-static DWORD WINAPI
-connect_thread (void *arg)
-{
-  sock_thread_data *std = (sock_thread_data *) arg;
-  std->ret = ::connect (std->socket, std->peer, *std->len);
-  return 0;
-}
-
-static DWORD WINAPI
-accept_thread (void *arg)
-{
-  sock_thread_data *std = (sock_thread_data *) arg;
-  std->ret = ::accept (std->socket, std->peer, std->len);
-  return 0;
-}
-
 /**********************************************************************/
 /* fhandler_socket */
 
@@ -520,7 +497,6 @@ out:
 int
 fhandler_socket::connect (const struct sockaddr *name, int namelen)
 {
-  BOOL interrupted = FALSE;
   int res = -1;
   BOOL secret_check_failed = FALSE;
   BOOL in_progress = FALSE;
@@ -530,18 +506,7 @@ fhandler_socket::connect (const struct s
   if (!get_inet_addr (name, namelen, &sin, &namelen, secret))
     return -1;
 
-  if (!is_nonblocking ())
-    {
-      sock_thread_data cd = { get_socket (), (sockaddr *) &sin, &namelen, -1 };
-      cygthread *thread = new cygthread (connect_thread, &cd, "connect");
-      HANDLE waitevt = CreateEvent(&sec_none_nih, FALSE, TRUE, NULL);
-      interrupted = thread->detach (waitevt);
-      CloseHandle (waitevt);
-      if (!interrupted)
-        res = cd.ret;
-    }
-  else
-    res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
+  res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
 
   if (res)
     {
@@ -596,9 +561,6 @@ fhandler_socket::connect (const struct s
   else
     set_connect_state (CONNECTED);
 
-  if (interrupted)
-    set_errno (EINTR);
-
   return res;
 }
 
@@ -638,19 +600,7 @@ fhandler_socket::accept (struct sockaddr
   if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
     *len = sizeof (struct sockaddr_in);
 
-  if (!is_nonblocking ())
-    {
-      sock_thread_data ad = { get_socket (), peer, len, -1 };
-      cygthread *thread = new cygthread (accept_thread, &ad, "accept");
-      HANDLE waitevt = CreateEvent(&sec_none_nih, FALSE, TRUE, NULL);
-      BOOL interrupted = thread->detach (waitevt);
-      CloseHandle (waitevt);
-      if (interrupted)
-	return -1;
-      res = ad.ret;
-    }
-  else
-    res = ::accept (get_socket (), peer, len);
+  res = ::accept (get_socket (), peer, len);
 
   if ((SOCKET) res == INVALID_SOCKET && WSAGetLastError () == WSAEWOULDBLOCK)
     in_progress = TRUE;
Index: net.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/net.cc,v
retrieving revision 1.143
diff -u -p -r1.143 net.cc
--- net.cc	13 Mar 2003 11:31:24 -0000	1.143
+++ net.cc	3 Jun 2003 12:43:04 -0000
@@ -773,7 +773,56 @@ cygwin_connect (int fd, const struct soc
   if (__check_invalid_read_ptr_errno (name, namelen) || !fh)
     res = -1;
   else
-    res = fh->connect (name, namelen);
+    {
+      bool was_blocking = false;
+      if (!fh->is_nonblocking ())
+        {
+	  int nonblocking = 1;
+	  fh->ioctl (FIONBIO, &nonblocking);
+	  was_blocking = true;
+	}
+      res = fh->connect (name, namelen);
+      if (was_blocking)
+        {
+	  if (res == -1 && get_errno () == EINPROGRESS)
+	    {
+	      size_t fds_size = howmany (fd + 1, NFDBITS) * sizeof (fd_mask);
+	      fd_set *write_fds = (fd_set *) alloca (fds_size);
+	      fd_set *except_fds = (fd_set *) alloca (fds_size);
+	      memset (write_fds, 0, fds_size);
+	      memset (except_fds, 0, fds_size);
+	      FD_SET (fd, write_fds);
+	      FD_SET (fd, except_fds);
+	      res = cygwin_select (fd + 1, NULL, write_fds, except_fds, NULL);
+	      if (res > 0 && FD_ISSET (fd, write_fds))
+	        res = 0;
+	      else if (res > 0)
+	        {
+		  res = -1;
+		  for (;;)
+		    {
+		      int err;
+		      int len = sizeof err;
+		      cygwin_getsockopt (fd, SOL_SOCKET, SO_ERROR,
+					 (void *) &err, &len);
+		      if (err)
+		        {
+			  set_errno (err);
+			  break;
+			}
+		      low_priority_sleep (0);
+		    }
+		}
+	      else
+	        {
+		  WSASetLastError (WSAEINPROGRESS);
+		  set_winsock_errno ();
+		}
+	    }
+	  int nonblocking = 0;
+	  fh->ioctl (FIONBIO, &nonblocking);
+	}
+    }
 
   syscall_printf ("%d = connect (%d, %p, %d)", res, fd, name, namelen);
 
@@ -1051,7 +1100,19 @@ cygwin_accept (int fd, struct sockaddr *
       || !fh)
     res = -1;
   else
-    res = fh->accept (peer, len);
+    {
+      if (!fh->is_nonblocking ())
+	{
+	  size_t fds_size = howmany (fd + 1, NFDBITS) * sizeof (fd_mask);
+	  fd_set *read_fds = (fd_set *) alloca (fds_size);
+	  memset (read_fds, 0, fds_size);
+	  FD_SET (fd, read_fds);
+	  res = cygwin_select (fd + 1, read_fds, NULL, NULL, NULL);
+	  if (res == -1)
+	    return -1;
+	}
+      res = fh->accept (peer, len);
+    }
 
   syscall_printf ("%d = accept (%d, %p, %p)", res, fd, peer, len);
   return res;


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]