Alan Barrett wrote:
> I found a horrible interaction between subversion and ssh.
>
> This works:
>
> svn log svn+ssh://host/repo/trunk | less
>
> This doesn't work:
>
> svn log svn+ssh://host/repo/trunk 2>&1 | less
>
> The symptom is that the output is truncated after the first few
> kilobytes.
>
> The underlying cause is this sequence of events:
>
> 1. The shell runs "svn" in such a way that both fd 1 (stdout) and fd 2
> (stderr) are connected to a pipe which goes to "less".
>
> 2. svn runs ssh, in such a way that ssh's fd 0 (stdin) and fd 1
> (stdout) are connected to pipes controlled by svn, but ssh's fd 2
> (stderr) is still connected to the pipe that goes to "less". In
> other words, all three of svn's fd 1 (stdout), svn's fd 2 (stderr),
> and ssh's fd 2 (stderr) are connected to the same place.
>
> 3. ssh puts its stderr into non-blocking mode. Because ssh's stderr
> and svn's stdout and stderr all go to the same place, this
> accidentally puts svn's stdout and stderr into non-blocking mode.
>
> 4. After a while, svn starts writing to stdout. The first few writes
> work fine. But after a few kilobytes, a write attempt gets an
> EAGAIN error (a.k.a. EWOULDBLOCK). The pipe is full and the write
> would have to block until "less" drains some data from the other
> end of the pipe; but the file descriptor is in non-blocking mode,
> so the write gets an error instead of blocking.
>
> 5. svn gives up. It tries to write an error message to stderr, but
> that also encounters an EAGAIN/EWOULDBLOCK error.
>
> As a workaround, I pointed the SVN_SSH environment variable to this
> script, and everything worked correctly:
>
> #!/bin/sh
> # Run ssh in such a way that a pipe through a "cat" process is
> # interposed between the inner fd 2 (stderr) seen by the ssh
> # command, and the outer fd 2 (stderr) seen by our caller (which
> # is typically "svn"). This insulates the outer fd 2 from ssh's
> # habit of putting the inner fd 2 into non-blocking mode.
> PATH=/bin:/usr/bin
> REAL_SSH=/usr/bin/ssh
> exec 4>&1
> exec "${REAL_SSH}" ${1+"$@"} 1>&4 2>&1 4>&- | cat 1>&2
>
> As a fix, I suggest that svn should connect ssh's stdout to a pipe
> that is managed by svn.
I assume you meant stderr here, since it already does so
with stdout (according to your message.)
The reason not to do this is that ssh uses stderr to prompt
for authentication credentials. By leaving stderr connected
to terminal (in most cases) the user can actually type
his password/passphrase/whatever to authenticate
to the server. If we redirect stderr, then this will no
longer work.
Thanks,
Joseph
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Mar 21 17:30:24 2006