In a pipeline, interrupt only one command

I need to pipe two programs, the first one can be interrupted only by sending a kill signal; how to kill it without killing the whole pipeline? For example how to interrupt yes in a moral equivalent of pipeline(`yes`, `wc -l`) using Ctrl-C, and get the line count? I tried doing yes = open(`yes`), and running run(pipeline(yes, `wc -l`)) asynchronously, but didn’t manage to catch InterruptException in a way that gives me back the wanted result.

EDIT: just running run(pipeline(`yes`, `wc -l`)) doesn’t give the result after Ctrl-C, I assume because the second command wc -l is also killed by Ctrl-C before it has a chance to print the result.

io = IOBuffer()
try
    p = run(pipeline(ignorestatus(`yes`); stdout=io))
catch e
    if e isa InterruptException
        kill(p, Base.SIGKILL)
    else
        rethrow()
    end
end
seekstart(io)
run(pipeline(`wc -l`; stdin=io))

Inspired by https://github.com/JuliaLang/Pkg.jl/blob/b4da4946735fe4c7c6bb3e2bc16af95b4e76e487/src/Operations.jl#L1728-L1745 (from this recent pull request which made Ctrl+C-ing tests much friendlier: https://github.com/JuliaLang/Pkg.jl/pull/2933)

1 Like

Thanks Mosè! Yes that’s a decent solution, the main problem being that everything from yes has to fit in memory (and minor inconvenience being that wc can run only after yes stops). But i will use that (writing ro a file instead) if no other solution is found.

1 Like