Tuesday, December 30, 2008

Deadlock avoidance when using redirected StandardInput, StandardOutput and StandardError with System.Diagnostics.Process

Lucian's VBlog - System.Diagnostics.Process: redirect StandardInput, StandardOutput, StandardError

“Sometimes you want to launch an external utility and send input to it and also capture its output. But it's easy to run into deadlock this way...

The deadlock in this case arises because "cat" (a standard unix utility) first reads from StandardInput, then writes to StandardOutput, then reads again, and so on until there's nothing left to read. But if its StandardOutput fills up with no one to read it, then it can't write any more, and blocks.

The MSDN documentation says, "You can use asynchronous read operations to avoid these dependencies and their deadlock potential. Alternately, you can avoid the deadlock condition by creating two threads and reading the output of each stream on a separate thread." So that's what we'll do...

Using threads to redirect without deadlock

' GOOD CODE: this will not deadlock.

Using p As New Diagnostics.Process

    p.StartInfo.FileName = "sort"

    p.StartInfo.UseShellExecute = False

    p.StartInfo.RedirectStandardOutput = True

    p.StartInfo.RedirectStandardInput = True

    p.Start()

    Dim op = ""

    ' do NOT WaitForExit yet since that would introduce deadlocks.

    p.InputAndOutputToEnd("world" & vbCrLf & "hello", op, Nothing)

    p.WaitForExit()

    p.Close()

    Console.WriteLine("OUTPUT:") : Console.WriteLine(op)

End Using

[GD: Click through for the InputAndOutputToEnd code block]

…”

I’ve got a redirect StdIn/StdOut/StdErr related project on the books and this tip might come in handy

No comments: