在Perl中使用子监视器时如何检查子进程是否处于活动状态

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将如何处理这些信号而不是信号如何工作.

ike*_*ami 5

您可以使用哈希来跟踪您拥有的孩子.

$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)