This is the mail archive of the cygwin@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]

Patch for slow rsync - select(2) bug


After finally getting bored with the poor performance of rsync on
Cygwin I decided to investigate.

Turns out that when using rsh or ssh as the transport, they soak up
99% of the CPU time. This is because they use non-blocking i/o, but
the Cygwin select() function incorrectly returns "ready for read or
write", even when there is no buffer space available, so they get
stuck in a loop calling select and read/write (which immediately
return EWOULDBLOCK).

The following patch fixes this problem by correctly initialising the
socket's "connect state" for rcmd/rexec sockets and socketpairs, and
then maintaining the state correctly across a fork.

Note, that this doesn't fix the other problem where rsync often hangs
at the end of a transfer. I'll look into this further when I have
time.

Nigel
-- 
                         Nigel Stephens         Mailto:nigel@mips.com
    _    _ ____  ___     MIPS Technologies      Phone.: +44 1223 706200
    |\  /|||___)(___     The Fruit Farm         Direct: +44 1223 706207
    | \/ |||    ____)    Ely Road, Chittering   Fax...: +44 1223 706250
     TECHNOLOGIES UK     Cambridge CB5 9PH      Cell..: +44 7976 686470
                         England                http://www.mips.com
Index: cygwin/ChangeLog
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/ChangeLog,v
retrieving revision 1.1947
diff -u -r1.1947 ChangeLog
--- cygwin/ChangeLog	2 Jul 2003 03:50:05 -0000	1.1947
+++ cygwin/ChangeLog	3 Jul 2003 20:59:50 -0000
@@ -1,3 +1,16 @@
+Thu Jul  3 21:54:18 2003  N Stephens  <nigel@mips.com>
+
+	* net.cc (cygwin_rcmd): Mark file handles of sockets returned by
+	rcmd() as CONNECTED state.
+	(cygwin_rexec): Similarly for rexec().
+	(socketpair): Mark both ends of a new socket pair as CONNECTED.
+
+	* fhandler_socket.cc (dup): Copy socket connect state to new file
+	handle.
+
+	* fhandler.h (fhandler_socket::get_connect_state): New method to
+	return socket connection state.
+
 2003-07-01  Christopher Faylor  <cgf@redhat.com>
 
 	* thread.cc: Remove _MT_SAFE conditional.
Index: cygwin/fhandler.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v
retrieving revision 1.163
diff -u -r1.163 fhandler.h
--- cygwin/fhandler.h	26 May 2003 09:54:01 -0000	1.163
+++ cygwin/fhandler.h	3 Jul 2003 20:59:50 -0000
@@ -410,6 +410,7 @@
   bool is_connect_pending () const {return had_connect_or_listen == CONNECT_PENDING;}
   bool is_connected () const {return had_connect_or_listen == CONNECTED;}
   void set_connect_state (int newstate) { had_connect_or_listen = newstate; }
+  int get_connect_state () const { return had_connect_or_listen; }
 
   int bind (const struct sockaddr *name, int namelen);
   int connect (const struct sockaddr *name, int namelen);
Index: cygwin/fhandler_socket.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_socket.cc,v
retrieving revision 1.106
diff -u -r1.106 fhandler_socket.cc
--- cygwin/fhandler_socket.cc	30 Jun 2003 13:07:36 -0000	1.106
+++ cygwin/fhandler_socket.cc	3 Jul 2003 20:59:51 -0000
@@ -320,6 +320,7 @@
   if (get_addr_family () == AF_LOCAL)
     fhs->set_sun_path (get_sun_path ());
   fhs->set_socket_type (get_socket_type ());
+  fhs->set_connect_state (get_connect_state ());
 
   if (winsock2_active)
     {
Index: cygwin/net.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/net.cc,v
retrieving revision 1.146
diff -u -r1.146 net.cc
--- cygwin/net.cc	19 Jun 2003 00:57:26 -0000	1.146
+++ cygwin/net.cc	3 Jul 2003 20:59:52 -0000
@@ -1997,7 +1997,10 @@
       if (res_fd >= 0)
 	fh = fdsock (res_fd, "/dev/tcp", res);
       if (fh)
-	res = res_fd;
+	{
+	  fh->set_connect_state (CONNECTED);
+	  res = res_fd;
+	}
       else
 	{
 	  closesocket (res);
@@ -2011,8 +2014,11 @@
 	  fh = NULL;
 	  if (newfd >= 0)
 	    fh = fdsock (newfd, "/dev/tcp", fd2s);
-	  if (fh)
-	    *fd2p = newfd;
+	  if (fh) 
+	    {
+	      *fd2p = newfd;
+	      fh->set_connect_state (CONNECTED);
+	    }
 	  else
 	    {
 	      closesocket (res);
@@ -2081,7 +2087,10 @@
       if (res_fd >= 0)
 	fh = fdsock (res_fd, "/dev/tcp", res);
       if (fh)
-	res = res_fd;
+	{
+	  fh->set_connect_state (CONNECTED);
+	  res = res_fd;
+	}
       else
 	{
 	  closesocket (res);
@@ -2096,7 +2105,10 @@
 	  if (newfd >= 0)
 	    fh = fdsock (newfd, "/dev/tcp", fd2s);
 	  if (fh)
-	    *fd2p = newfd;
+	    {
+	      fh->set_connect_state (CONNECTED);
+	      *fd2p = newfd;
+	    }
 	  else
 	    {
 	      closesocket (res);
@@ -2272,6 +2284,7 @@
 	fh->set_sun_path ("");
 	fh->set_addr_family (family);
 	fh->set_socket_type (type);
+	fh->set_connect_state (CONNECTED);
 
 	cygheap_fdnew sb1 (sb0, false);
 
@@ -2283,6 +2296,7 @@
 	    fh->set_sun_path ("");
 	    fh->set_addr_family (family);
 	    fh->set_socket_type (type);
+	    fh->set_connect_state (CONNECTED);
 
 	    sb[0] = sb0;
 	    sb[1] = sb1;

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

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