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