Tyrrrz / CliWrap

Library for running command-line processes
MIT License
4.32k stars 264 forks source link

Command can deadlock if the process writes large output and one of the targets inside `PipeTarget.Merge(...)` throws #212

Closed Tyrrrz closed 1 year ago

Tyrrrz commented 1 year ago

Version

3.6.3 / master

Details

If a process generates a lot of output (bigger than the buffer size for stdout/stderr), and that output is piped through PipeTarget.Merge(...) to multiple targets, and one of those targets throws, then the process hangs forever.

See below for code repro.

Origin issue: https://github.com/Tyrrrz/YoutubeDownloader/issues/343

Steps to reproduce

// Arrange
void HandleStdOut(string line) => throw new Exception("Expected exception");

var target = PipeTarget.Merge(
    PipeTarget.ToStream(Stream.Null),
    PipeTarget.ToDelegate(HandleStdOut)
);

var cmd = Cli.Wrap("dotnet")
    .WithArguments(a => a
        .Add(Dummy.Program.FilePath)
        .Add("generate text")
        .Add("--target").Add("all")
        .Add("--lines").Add(100_000)
    ) | target;

// Act & assert
await Assert.ThrowsAnyAsync<Exception>(async () => await cmd.ExecuteAsync());