2

更新:

我有一个单元测试(认为它是 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 并没有停止,它进入了一个失效状态(我之前称之为“僵尸样”)。据我所知,这是一个已完成的过程,通过/proc不可用kill(0, $pid)但可见。ps

在实际的过程 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 的输出中看到 theExiting...或 the 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

注意defunctY 的状态,注意有两个进程。我没有开始两个,它没有分叉,所以我假设HTTP::Daemon分叉。我明确修改了 X 以发送不同的信号。这次我发送了SIGINT,就像我按 Ctrl-C 时它实际上停止了挂起X和两者Y。这次我收到了Signal receivedY 的消息,但它仍然进入失效状态并且仍然有两个进程。

我的问题是针对HTTP::DaemonPerl 而不是。究竟是什么HTTP::Daemon(源自IO::Socket::INET)实际上导致了这种混乱,为什么?其次,我如何适应YHTTP::Daemon 正在做的事情?

4

1 回答 1

0

好吧,我第一次可能没有以最好的方式问这个问题。但这并不意味着它不是一个有效的答案,我知道那里的某个人可能会持有答案。但再一次,我在这里,完成了我自己问题的答案。与其重复我找到的答案,不如说是它的全部荣耀:

HTTP::Daemon 的奇怪阻塞问题

于 2013-09-05T19:23:55.733 回答