1
votes

I am extending a .NET4 command-line application that, among other things, creates an external process to call svn.exe to pull some data from our repository. The issue is that when our account password is changed, the authentication fails and SVN prompts for the account password.

SVN does this by writing a prompt to the standard error. The output looks like:

STDOUT: Updating '.':
STDERR: Authentication realm: <http://{host}:8080> VisualSVN Server
STDERR: Password for 'joe.smith':

Where I think it's going wrong is that the second "line" from the child process (CP henceforth) does not include a newline and is probably not getting picked up by BeginErrorReadLine() before the parent process (PP) blocks on the standard input stream. My guess is supported by the fact that closing the input stream on the CP causes the remaining data from both the output- and error-stream to be handled by my DataReceivedEventHandler callbacks.

The sequence of events appear to be:

  1. CP starts writing to STDOUT.
  2. If cached authentication credentials are wrong, CP starts writing the above message to STDERR.
  3. Depending on whether I read synchronously or asynchronously from STDERR, the following happens:
    • Synchronously: The CP appears to await input from STDIN while the PP awaits more data from STDERR. Even peeking or checking if the stream is closed results in deadlock.
    • Asynchronously: The second line is not read before the CP waits to read from its STDIN.

Assuming I have correctly diagnosed the problem, I am still at a loss as to what to do about it.

As for options I have attempted:

  • Following this MSDN article, I toyed with attempting synchronously reading from standard-error. This seemed fraught with danger, as any method blocked indefinitely as soon as it read the last character fron standard-error.
  • The previous link also advised "Alternately, you can avoid the deadlock condition by creating two threads and reading the output of each stream on a separate thread.", however my efforts along this track were evidently quite misguided. I don't see how threads can help when, by the time I know I've hit the end of the stream, it's too late.

To clarify, how can I safely read to the end of the standard error stream without causing a deadlock?

1

1 Answers

1
votes

I think your analysis is correct. I've had to do a bit of CP stdio redirection, and it's always a pain on Win32 (designed as a UI platform rather than command-line...).

Anyway, you could try reading from the actual streams (using BeginRead, or ReadAsync if .NET 4.5) and doing the Encoding conversion yourself. That would be my first attempt.

Otherwise, you'd have to use multiple threads. I've done this before, and it's a pain.

Either way, you're not actually waiting for the end of the CP's stderr. Just monitor it for you magic string. Most console programs do not close their stdout or stderr until they exit, so you can't read it all the way to the end until it has exited.