【问题标题】:Perl kill child process also exits parent?Perl杀死子进程也退出父进程?
【发布时间】:2015-10-24 18:04:02
【问题描述】:

我正在用 PERL 编写一个仿真存根来测试另一个程序。下面,代码运行一个循环来检查命令(initialize、exit、start_trace、stop_trace)。当读取“start_trace”命令时,它会派生一个每秒只吐出数字的进程。我想用“stop_trace”杀死孩子,但它也杀死了父母。我错过了什么?

use warnings;
use strict;

my $pid = undef;

$| = 1;

$SIG{TERM} = sub { 
    if ($pid == 0) {
        print "Parent, not terminating\n";
    } else {
        print "Child ($pid) terminating\n"; 
        exit(1);
    }
};


print "entering loop\n";
while (1) {
    while (<>) {
        my ($command, @args) = split();
        if ($command eq "exit") {
            exit 1;
        }
        elsif ($command eq "initialize") {
            print "s: ok\n";
        }
        elsif ($command eq "start_trace") {
            if (defined $pid) {
                print "child already running\n";
            } else {
                $pid = fork();
                if ($pid == -1) {
                    print "failed to fork\n";
                    exit 1;
                }
                elsif ($pid == 0) {
                    print "Parent\n";
                }
                else {
                    my $timestamp = 0;
                    while (1) {
                        for (my $i = 0; $i < 12; ++$i) {
                            printf "%.3f %.0f %.2f %.1f\n", 
                                ++$timestamp,
                                0,
                                0,
                                100 * rand()
                            ;
                        }
                        sleep(1);
                    }
                }
            }
        }
        elsif ($command eq "stop_trace") {
            kill "TERM", $pid;
            #waitpid($pid, 0);
            $pid = undef;
        }
        else {
            printf "s: unknown command $command\n";
        }
    }
}

输出(不是标准输入和标准输出都混合在一起,但我输入的是“stop_trace”)

stop85.000 0 0.00 66.6
86.000 0 0.00 43.3
87.000 0 0.00 82.3
88.000 0 0.00 62.8
89.000 0 0.00 43.5
90.000 0 0.00 50.0
91.000 0 0.00 8.8
92.000 0 0.00 89.3
93.000 0 0.00 61.4
94.000 0 0.00 92.4
95.000 0 0.00 46.6
96.000 0 0.00 53.9
_trace
Child (26644) terminating
Parent, not terminating
%

但他们都退出了!为什么?

【问题讨论】:

    标签: perl process fork


    【解决方案1】:

    我认为这里有一个逻辑错误 - 当你 fork() 时发生的是两位代码分支 - 而 唯一 在这一点上的区别是子进程有一个来自 @ 的返回码987654321@ 为零,而他父母的返回码为$pid

    它将子pid返回给父进程,0返回给子进程,如果fork不成功则返回undef。

    所以我认为你在测试时的逻辑是倒退的:

    elsif ($pid == 0) {
        print "Parent\n";
    }
    

    实际上是您的 父母 进入了该 while 循环,而您的子进程仍在 while 循环中读取标准输入。

    我认为这就是您遇到问题的原因 - 因为孩子正在接收 stop_trace 并发出 kill "TERM", 0 而不是它应该杀死的孩子 pid。

    我实际上并不完全确定当您杀死 pid 0 时应该发生什么。但从外观上看 - 它无论如何都在向两个进程发出信号。

    您的信号处理程序中存在相同的逻辑错误 - 您的父级已被杀死,因为它已将 $pid 设置为 0。我不是 100% 确定为什么这会导致你的孩子退出 - 你确定它确实是这样,而且你没有在 while(1) 中积累陈旧的进程并关闭 STDIN

    很容易检查 - 将 print "$$: killing child with pid $pid\n"; 粘贴到 stop_trace 分支中。

    哦 - 如果失败,则 perl 中的 fork 返回 undef 而不是 -1

    【讨论】:

    • 哦,天哪,你是对的。我在处理程序和循环中将 == 0 更改为 != 0 ,一切都很好。谢谢你。我应该删除这篇文章吗?
    • 我不认为这是必要的 - 这是一个合理的问题,可能对未来的读者有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 2017-08-05
    • 2011-09-23
    相关资源
    最近更新 更多