gpt4 book ai didi

perl - AnyEvent::Fork 如何等待 child

转载 作者:行者123 更新时间:2023-12-01 12:38:35 24 4
gpt4 key购买 nike

我正在查看 AnyEvent::Fork模块。我有 20 个外部脚本,我想并行调用(一次 6 个),并在全部完成后汇总它们的输出。我不知道如何实现这一目标。

模块中的示例代码(仅调用 1 个子代码)有问题。我只是在代码中添加了一个简单的 sleep ,以不立即返回,父进程立即退出,而无需等待子进程。

open my $output, ">/tmp/log" or die "$!";

AnyEvent::Fork
->new
->eval ('
# compile a helper function for later use
sub run {
my ($fh, $output, @cmd) = @_;

# perl will clear close-on-exec on STDOUT/STDERR
open STDOUT, ">&", $output or die;
open STDERR, ">&", $fh or die;

### Added by me to demonstrate that
### $cv->recv returns immediately.
sleep 5;

exec @cmd;
}
')
->send_fh ($output)
->send_arg ("/bin/echo", "hi")
->run ("run", my $cv = AE::cv);

my $stderr = $cv->recv;

结果是 /tmp/log 是空的。我不明白这里是如何使用 condvar 的,它不在文档中。我可以使用 condvar 获取正在运行的 child 的数量吗?

请帮助解决这个问题。

更新这里的主要问题是 parent 不等待 child 完成。

最佳答案

这里的问题是父进程和子进程是独立的进程,可以相互独立运行,所以如果一个应该等待另一个,则需要显式同步。有很多方法可以做到这一点,最简单的方法是使用 AnyEvent::Fork::RPC,然后向 child 发送一个“等待”请求,它会在完成后回答。

要使用裸 AnyEvent::Fork 做到这一点,最简单的方法是利用 ->run 提供的双向管道:

  AnyEvent::Fork
->new
->run (sub {
my ($fh) = @_;
sysread $fh, my $dummy, 1; # will wait for data, or eof
... done, you can now call e.g. $cv->send

sysread 将尝试从子进程读取。如果子进程从不发送任何东西,这将阻塞父进程直到子进程退出,因为在那一刻,子进程将关闭它的管道末端并且 sysread 得到一个 EOF。

当然,在 AnyEvent 程序中您可能不想阻塞,所以您使用 I/O 观察器:

 ->run (sub {
my ($fh) = @_;
my $rw; $rw = AE::io $fh, 0, sub {
... read data received, or EOF
undef $rw;
... done, you can now call e.g. $cv->send;
}
});

这个技巧也可以用于外部命令(在你的例子中是 exec),通过清除子管道的 close-on-exec 状态,然后将它传递给 exec'ed 程序 - 在这种情况下,当所有继承管道的程序退出时,管道将发出 EOF 信号。

这应该可以帮助您入门。还有其他方法可以做到这一点,但大多数甚至所有好的方法都会涉及一些通信管道,最简单的方法是使用 AnyEvent::Fork 提供的管道。

关于perl - AnyEvent::Fork 如何等待 child ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27153465/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com