加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

当发送到包含子节点的perl脚本时,SIGINT(^ C)会发生什么情况?

发布时间:2020-12-15 21:27:21 所属栏目:大数据 来源:网络整理
导读:我有一个Perl脚本. 每个fork运行外部程序,解析输出,并将输出转换为可存储文件. 然后由父母读取可存储的文件,并分析来自每个孩子的总数据,然后继续重复前一个分支,否则父节点停止. 当我发出^ C,而一些孩子仍在运行外部程序时究竟发生了什么?父进程脚本在前台
我有一个Perl脚本.

每个fork运行外部程序,解析输出,并将输出转换为可存储文件.

然后由父母读取可存储的文件,并分析来自每个孩子的总数据,然后继续重复前一个分支,否则父节点停止.

当我发出^ C,而一些孩子仍在运行外部程序时究竟发生了什么?父进程脚本在前台调用,我认为,尽管分叉仍然保留在前台.

SIGINT是否传递给所有的孩子,即父母,父母的孩子和孩子们调用的外部程序?

更新:

我应该补充一下,看起来当我发出SIGINIT时,我脚本的孩子所调用的外部程序似乎承认了信号并终止了.但孩子们,或者也许是父母节目,继续下去.这对我来说都不清楚

更新2:

关于tchrist的评论,使用Perl的system()命令调用外部程序.

事实上,tchrist的评论似乎也包含了我正在寻找的解释.经过一些更多的调试,根据我的程序的行为,看来,事实上,SIGINT正在从父代传递给所有的孩子,从所有的孩子传递给他们所有的孩子(外部程序).

因此,根据tchrist的评论,似乎正在发生的事情是,CTRL-C正在杀死导致孩子们离开system()命令的外部程序,而没有更多的东西.

虽然我有我的孩子检查系统()中调用的退出状态,但我假设CTRL-C会从父母身上杀死一切,而不是导致创建更多的处理,这是什么发生!

解决方案(对我的问题):

我需要在父节点创建SIGINT的信号处理程序.然后,信号处理程序将向每个孩子发送SIGTERM(我认为也会向孩子的孩子发送一个SIGTERM),然后使父母正常退出.虽然这个有点明显的解决方案可能会有固定的东西,但我想了解我对于SIGINT在Perl中的划分行为的误解.

解决方法

就信号而言,Perl的内置系统功能与标准C库中的C系统(3)功能一样.如果您正在使用Perl的system()或管道打开或反引号,那么父级 – 一个调用系统而不是一个调用系统 – 将在孩子们正在运行时将IGNORE任何SIGINT和SIGQUIT.如果你自己使用一些变种的叉子,等等:执行三重奏,那么你必须自己考虑这些问题.

考虑在vi中长时间使用系统(“vi somefile”)并按^ C时会发生什么?只有vi需要(非致命的)SIGINT;父母忽略它.这是正确的行为.这就是为什么C以这种方式工作,这就是为什么Perl以这种方式工作的原因.

你必须记住的是,只是因为^ C向前台进程组(即使那些不同的有效UID或GID)的所有进程发送一个SIGINT,这并不意味着它会导致所有这些进程退出. A ^ C只是一个SIGINT,意图中断一个进程,而不是SIGKILL,意图终止,没有问题.

有很多种程序,只要没有警告即可杀死是错误的;编辑只是一个这样的例子.邮件可能是另一个.对此非常小心.

各种程序有选择地忽略,陷阱或阻止(意味着延迟交付)各种信号.只有SIGINT的默认行为才能使进程退出.您可以了解这是否发生,实际上哪些信号会导致其发生(除此之外),传统操作系统上有这样的代码:

if ($wait_status = system("whatever")) {
    $sig_killed   = $wait_status & 127;
    $did_coredump = $wait_status & 128;
    $exit_status  = $wait_status >>  8;
    # now do something based on that...
}

请注意,例如,^ C’d vi将不会有一个等待状态字表示它死于未被捕获的SIGINT,因为没有一个:它捕获它.

有时候,你的孩子们会去自己背后的孩子.凌乱但真实.因此,我有时候已经知道以这种方式种族灭绝所有已知和未知的后代:

# scope to temporize (save+restore) any previous value of $SIG{HUP}
{
    local $SIG{HUP} = "IGNORE";
    kill HUP => -$$;   # the killpg(getpid(),SIGHUP) syscall
}

那当然不符合SIGKILL或SIGSTOP的功能,这不符合IGNOREd的要求.

您可能想要注意的另一件事是,在5.8版本之前,Perl中的信号处理从来不是可靠的安全操作.现在是这个版本问题.如果你还没有这样做,那么你应该肯定会在deferred signals in the perlipc manpage上阅读,也许在PERL_SIGNALS envariable in the perlrun manpage.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读