HTTP::D aemon 分叉未在 SIGTERM 上收获的子进程



更新:

我有一个单元测试(考虑一下X)。有一个子流程(Y)。Y没有明确地分叉。X分叉是为了执行Y。这是X:

warn("Starting Y...");
my $pid;
die "failed to fork" unless($pid = fork);
unless($pid) {
    { exec "exec /usr/bin/Y"; };
    warn "failed: $!";
    _exit(0);
}
# Do something to test Y.
warn("Stopping Y...");
my $st;
do {
    kill(15, $pid);
    $st = waitpid($pid, WNOHANG);
} while ($st > 0);
warn("Y has stopped");

我从X得到的输出是:

Starting Y... at ...
Some stuff.
Stopping Y.... at ...
Y has stopped at ...

这将表明Y已经接收到信号并停止。但Y并没有停止,它进入了一种不起作用的状态(我之前称之为"僵尸般")。据我所知,这是一个已完成的过程,对kill(0, $pid)不可用,但通过ps和/proc可见。

在实际的过程Y中,它是一个不同的故事:

sub goodbye {
    warn("Received signal");
    exit(0);
}
$SIG{TERM} = &goodbye;
$SIG{INT} = &goodbye;
warn("Starting server...");
my $d = HTTP::Daemon->new(
    LocalAddr => "127.0.0.1",
    LocalPort => 81,
    Reuse => 1
);
while (my $c = $d->accept) {
    # Do some stuff
    $c->close;
}
warn("Exiting...");

我从未在Y的输出中看到Exiting...Received signal,只有Starting server消息。Y正在运行并接受来自X的所有连接,从而通过测试;它就是停不下来。

这是X信号Y前后的一些调试的输出。

DEBUG before kill:
root      2843  2795  0 11:23 pts/4    00:00:00 /usr/bin/perl /bin/Y
root      2844  2843  4 11:23 pts/4    00:00:00 /usr/bin/perl /bin/Y
DEBUG after kill:
root      2843  2795  0 11:23 pts/4    00:00:00 [Y] <defunct>
root      2844     1  4 11:23 pts/4    00:00:00 /usr/bin/perl /bin/Y

注意Y的defunct状态,并注意有两个过程。我没有开始两个,它没有分叉,所以我假设HTTP::Daemon分叉。我明确地修改了X以发送不同的信号。这一次我发送了SIGINT,就像我点击Ctrl-C时一样,它实际上停止了挂起的X和两个Ys。这次我从Y收到了Signal received消息,但它仍然处于无效状态,仍然有两个进程。

我的问题针对的是HTTP::Daemon,而不是Perl。HTTP::Daemon(来源于IO::Socket::INET)究竟是什么导致了这种混乱?为什么?其次,我如何调整Y以应对HTTP::Daemon正在做的事情?

好吧,我第一次可能没有以最好的方式问这个问题。但这并不意味着这不是一个有效的答案,因为我知道有人可能会给出答案。但是,我再次来到这里,实现了我自己问题的答案。与其重复我找到的答案,不如说它在这里大放异彩:

HTTP::Daemon 的奇怪阻塞问题

最新更新