Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl 6 blocks on awaiting killed Proc::Async

Tags:

raku

I have a perl6 program that runs a external program via Proc::Async and tries to read its stdout. It's possible that the portion of the code that is supposed to read the stdout somehow fails to do so, but other parts of the program will actually kill the external process in order to clean things up. However, after killing such process, and then await the promise, it blocks forever..., how can I avoid perl6 from blocking on awaiting a killed Proc::Async whose stdout is piped but not consumed? I think the following snippet illustrate the problem:

#!/usr/bin/env perl6
#

my $proc = Proc::Async.new(<cat /dev/urandom>);
my $supply = $proc.stdout(:bin);
my $promise = $proc.start;

$proc.ready.then: {
    shell <<ps auxf | grep [u]random>>;
    put "Terminating process {$_.result} …";
    $proc.kill(SIGTERM);
}
sleep 1;
if shell(<<ps auxf | grep [u]random>>).exitcode ≠ 0 {
    put "processed killed!";
}

put "awaiting $proc ({$proc.command}) …";
await $promise;  # <--- blocked here :(
like image 377
cowbaymoo Avatar asked Jun 26 '19 09:06

cowbaymoo


1 Answers

The Promise returned from start is only kept once any obtained Supply of the output streams has delivered all of its events. This means one can assume that all output has been delivered by the time the Promise is kept, which overall greatly simplifies working with Proc::Async (without this behavior, we'd likely see a good number of buggy programs that lose output). However, if that Supply is never tapped, then there's no way for that to happen, thus the hang.

The solution is to .tap the stdout Supply without providing any callback:

$proc.stdout(:bin).tap;

Which will simply discard the output.

like image 61
Jonathan Worthington Avatar answered Oct 22 '22 15:10

Jonathan Worthington