Skip to content

ExecuteAsync hangs forever (and leaves the child blocked) when the output handler throws or a strict encoding hits a decode error #89

Description

@matt-edmondson

What's wrong

When a read faults, AsyncProcessStreamReader.Start breaks out of its read loop (RunCommand/AsyncProcessStreamReader.cs:74-77) and stops reading both pipes. A read faults when the handler callback throws, or when the handler's Encoding uses throwOnInvalidBytes: true, a case the code explicitly supports ("carries a decode error out to the caller").

RunCommand.cs:484-485 then awaits:

await Task.WhenAll(outputReader.Start(ct), process.WaitForExitAsync(ct));

WhenAll doesn't complete until the process exits, and nothing kills the process. Once the child writes more than the pipe buffer holds (≈64 KB on Linux, less on Windows), it blocks on write() forever. The call never returns, and the exception is never surfaced.

Reproduction (Linux, net10.0)

  • new OutputHandler(s => throw new InvalidOperationException()) with sh -c "echo first; sleep 0.5; head -c 1000000 /dev/zero" → the task is still pending after 10 s, and the head process is still alive.
  • encoding: new UTF8Encoding(false, throwOnInvalidBytes: true) with sh -c "printf '\377\n'; sleep 0.5; head -c 1000000 /dev/zero" → the task is still pending after 10 s.

Suggested fix

In RunAsync, observe the reader task on its own. If it faults, call the existing TryKill(process) (killing the whole process tree), then await the exit and rethrow the read exception. For example:

Task read = outputReader.Start(ct);
try { await read; } catch { TryKill(process); throw; }
await process.WaitForExitAsync(ct);

Acceptance criteria

Both repros throw the handler or decode exception promptly (well under a second after the fault), and no child process is left running.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingreadyFully specified; implement as written

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions