cygwin performance problem

Damien Miller djm at mindrot.org
Sun Apr 23 23:01:33 EST 2006


On Sun, 23 Apr 2006, Corinna Vinschen wrote:

> For the curious, the culprit was the select implementation for pipes.
> There's no Windows equivalent for the select function which works on
> pipes.  The only function available to test if data is available on a
> pipe is a function called "PeekNamedPipe", which is non-blocking.
>
> So a select implementation for pipes has to do something along the lines
> of a busy loop, testing the pipe with PeekNamedPipe until data is
> available.  However, such a loop has the disadvantage to take as much
> CPU as it can get, so the Cygwin loop used a 10ms sleep per iteration,
> to keep the CPU usage tolerable.

In this case, shouldn't cygwin be using socketpair() for interprocess
communication everywhere? (assuming that there is a select()-like 
function available in the Win32 API). This switch can be made by 
deleting the following line from "*-*-cygwin*)" block:

	AC_DEFINE(USE_PIPES, 1, [Use PIPES instead of a socketpair()])

To fully use socketpairs, you will need the following patch to scp.c,
as it doesn't seem to care right now:

Index: scp.c
===================================================================
RCS file: /var/cvs/openssh/scp.c,v
retrieving revision 1.155
diff -u -p -r1.155 scp.c
--- scp.c	23 Apr 2006 02:04:46 -0000	1.155
+++ scp.c	23 Apr 2006 12:58:15 -0000
@@ -181,7 +181,12 @@ do_local_cmd(arglist *a)
 int
 do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
 {
-	int pin[2], pout[2], reserved[2];
+	int reserved[2];
+#ifdef USE_PIPES
+	int pin[2], pout[2];
+#else
+	int pinout[2];
+#endif
 
 	if (verbose_mode)
 		fprintf(stderr,
@@ -195,11 +200,13 @@ do_cmd(char *host, char *remuser, char *
 	 */
 	pipe(reserved);
 
-	/* Create a socket pair for communicating with ssh. */
-	if (pipe(pin) < 0)
-		fatal("pipe: %s", strerror(errno));
-	if (pipe(pout) < 0)
+#ifdef USE_PIPES
+	if ((pipe(pin) == -1) || (pipe(pout) == -1))
 		fatal("pipe: %s", strerror(errno));
+#else /* USE_PIPES */
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pinout) == -1)
+		fatal("socketpair: %s", strerror(errno));
+#endif /* USE_PIPES */
 
 	/* Free the reserved descriptors. */
 	close(reserved[0]);
@@ -209,12 +216,25 @@ do_cmd(char *host, char *remuser, char *
 	do_cmd_pid = fork();
 	if (do_cmd_pid == 0) {
 		/* Child. */
+#ifdef USE_PIPES
 		close(pin[1]);
 		close(pout[0]);
-		dup2(pin[0], 0);
-		dup2(pout[1], 1);
+		if ((dup2(pin[0], STDIN_FILENO) == -1) ||
+		    (dup2(pout[1], STDOUT_FILENO) == -1)) {
+			fprintf(stderr, "dup2: %s\n", strerror(errno));
+			_exit(1);
+		}
 		close(pin[0]);
 		close(pout[1]);
+#else /* USE_PIPES */
+		close(pinout[0]);
+		if ((dup2(pinout[1], STDIN_FILENO) == -1) ||
+		    (dup2(pinout[1], STDOUT_FILENO) == -1)) {
+			fprintf(stderr, "dup2: %s\n", strerror(errno));
+			_exit(1);
+		}
+		close(pinout[1]);
+#endif /* USE_PIPES */
 
 		replacearg(&args, 0, "%s", ssh_program);
 		if (remuser != NULL)
@@ -229,10 +249,16 @@ do_cmd(char *host, char *remuser, char *
 		fatal("fork: %s", strerror(errno));
 	}
 	/* Parent.  Close the other side, and return the local side. */
+#ifdef USE_PIPES
 	close(pin[0]);
 	*fdout = pin[1];
 	close(pout[1]);
 	*fdin = pout[0];
+#else /* USE_PIPES */
+	close(pinout[1]);
+	*fdout = pinout[0];
+	*fdin = pinout[0];
+#endif /* USE_PIPES */
 	signal(SIGTERM, killchild);
 	signal(SIGINT, killchild);
 	signal(SIGHUP, killchild);




More information about the openssh-unix-dev mailing list