Sma*_*elf 0 unix perl events posix anyevent
我正在尝试使用AnyEvent和EV实现一些代码.我想安装一个儿童观察员(我想在下面做的样机)
use Modern::Perl;
use AnyEvent;
use EV;
my $SIG{QUIT} = \&kill_child;
my $exit_status = undef;
my $pid = fork or exec 'child.pl';
my $w = AnyEvent->child(pid => $pid, cb => sub { $exit_status = $_[2]; cleanup_after_child(); });
my $t = AE::timer 0, 5, sub { say $exit_status; fork_another_process(); };
AnyEvent->condvar->recv;
sub kill_child{
foreach my $signal (qw(HUP QUIT INT KILL)){
if(child_alive()){
kill($signal,$pid);
sleep 1;
}
}
exit; #Probably wrong
}
Run Code Online (Sandbox Code Playgroud)
我想帮助编写child_alive()以及找出各种回调以及在kill_child()中放置一个出口.我需要确保在进程退出之前调用cleanup_after_child().
使用AnyEvent Signal观察器会有帮助吗?我的目标是能够安全地关闭守护进程,首先杀死进程子进程并清理它们.我已经问了一个相关问题的问题(等待perl中的子进程)并且希望防止在退出处理期间发生该错误.
谢谢
编辑:以下是否适用于child_alive()函数?
sub child_alive{
return defined($exit_status)?1:0;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,一旦子项退出,是否已经调用了回调,还是只在EventLoop的下一次迭代中执行回调?如果是这样,我怎样才能在处理完所有信号后退出?我只是删除所有事件,如:
$w = undef;
$t = undef;
Run Code Online (Sandbox Code Playgroud)
对不起,我更想弄清楚AnyEvent将如何处理这些信号而不是信号如何工作.
您可以使用哈希来跟踪您拥有的孩子.
$children{$pid} = 1; # On creation.
delete($children{$pid}); # On reaping.
keys(%children) # Lists existing children.
Run Code Online (Sandbox Code Playgroud)
所以剩下的就是等待所有的孩子完成,并且在AnyEvent->child文档中已经有了一个例子.
总而言之,我们得到了
my $done = AnyEvent->condvar;
my %children;
my $spawner;
sub ae_sleep {
my ($dur) = @_;
my $done = AnyEvent->condvar;
my $t = AnyEvent->timer(after => $dur, cb => sub { $done->send });
$done->recv;
}
sub kill_children {
for my $sig (qw( HUP QUIT INT KILL )) {
last if !%children;
kill($sig => $_) for keys(%children);
ae_sleep(1);
}
}
$SIG{QUIT} = sub {
$spawner = undef; # Stop creating new children.
kill_children(); # Kill existing children.
$done->recv; # Wait for children to be reaped.
exit(0);
}
Run Code Online (Sandbox Code Playgroud)
sub create_child {
my $pid = ...;
$done->begin;
$children{$pid} = AnyEvent->child(
pid => $pid,
cb => sub {
my ($pid, $status) = @_;
delete($children{$pid});
warn "pid $pid exited with status $status";
$done->end;
},
);
}
$spawner = AnyEvent->timer(
after => 0,
interval => 5,
cb => \&create_child.
);
AnyEvent->condvar->recv; # Wait "for ever".
Run Code Online (Sandbox Code Playgroud)