Perl 6 блоков в ожидании убитого Proc :: Async - PullRequest
7 голосов
/ 26 июня 2019

У меня есть программа perl6, которая запускает внешнюю программу через Proc::Async и пытается прочитать ее stdout. Возможно, что часть кода, которая должна считывать стандартный вывод, каким-то образом не справляется, но другие части программы на самом деле убивают внешний процесс, чтобы очистить вещи. Тем не менее, после завершения такого процесса, а затем в ожидании обещания, он блокируется навсегда ..., как я могу избежать блокирования perl6 при ожидании убитого Proc::Async, чей stdout передается по каналу, но не расходуется? Я думаю, что следующий фрагмент иллюстрирует проблему:

#!/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 :(

1 Ответ

7 голосов
/ 26 июня 2019

Promise, возвращаемое из start, сохраняется только после того, как любой полученный Supply выходных потоков доставил все свои события.Это означает, что можно предположить, что все выходные данные были доставлены к моменту сохранения Promise, что в целом значительно упрощает работу с Proc::Async (без такого поведения мы, вероятно, увидели бы большое количество программ с ошибками, которые теряют вывод),Однако, если это Supply никогда не происходит, то это невозможно, поэтому зависание.

Решение состоит в том, чтобы .tap stdout Supply без предоставления какого-либо обратного вызова:

$proc.stdout(:bin).tap;

, который просто отбрасывает вывод.

...