【问题标题】:Why doesnt SIGINT get caught here?为什么 SIGINT 没有在这里被抓到?
【发布时间】:2011-03-15 22:27:05
【问题描述】:

这里发生了什么?我以为 SIGINT 会被发送到前台进程组。

(我想,也许那个 system() 正在运行一个 shell,它正在为子进程创建一个新的进程组?谁能证实这一点?)

% perl
local $SIG{INT} = sub { print "caught signal\n"; };
system('sleep', '10');

然后立即按 ctrl+d 然后按 ctrl+c 并注意从未打印过“caught signal”。

我觉得这是一件简单的事情......无论如何要解决这个问题?问题是,当通过系统运行一堆命令时,会导致按住 ctrl+c 直到所有迭代完成(因为 perl 永远不会得到 SIGINT)并且相当烦人......

如何解决这个问题? (我已经直接使用 fork() 进行了测试,并且知道这是可行的......目前这不是一个可接受的解决方案)

更新:请注意,这与“睡眠”无关,只是该命令需要一些任意长的时间来运行这一事实,这是相当大的比它周围的 perl 还多。如此之多以至于按 ctrl+c 被发送到命令(因为它在前台进程组中?)并且以某种方式设法永远不会被发送到 perl。

【问题讨论】:

    标签: linux perl process signals


    【解决方案1】:

    来自perldoc system

    由于 SIGINT 和 SIGQUIT 在系统执行期间被忽略, 如果您希望程序在收到这些信号时终止,您需要根据返回值自行安排。

    @args = ("command", "arg1", "arg2");
    system(@args) == 0
       or die "system @args failed: $?"
    

    如果您想手动检查系统故障,您可以检查所有可能的故障 通过检查 $?像这样:

    if ($? == -1) {
        print "failed to execute: $!\n";
    }
    elsif ($? & 127) {
        printf "child died with signal %d, %s coredump\n",
           ($? & 127),  ($? & 128) ? 'with' : 'without';
    }
    else {
        printf "child exited with value %d\n", $? >> 8;
    }
    

    或者,您可以使用来自 POSIX 模块的 W*() 调用检查 ${^CHILD_ERROR_NATIVE} 的值

    【讨论】:

    • 我认为我需要重新阅读文档:-/ 谢谢。
    • 我要补充一点,您需要检查孩子的返回值的原因是您的 shell 将 ^c/INT 传递给整个进程组、perl 和孩子,在这种情况下终止你的孩子sleep 10。如果你只是从另一个 shell 中kill -INT $perl_pid,perl 会很高兴地给你 SIG_IGNore。
    【解决方案2】:

    我不太明白你在这里想要达到的目标......但你是否尝试过简单地比较:

    perl -wle'local $SIG{INT} = sub { print "caught signal"; }; sleep 10;'
    

    您能解释一下您要达到什么效果,以及为什么要调用 shell?可以不涉及shell,直接调用外部程序吗?

    【讨论】:

    • 请参阅我的更新部分,“睡眠”与它无关......它只是一些任意进程的占位符。它可以很容易地用“grep something”切换,因为它期望从标准输入读取数据
    • @xyld:我意识到 sleep 是一个占位符。我在问你为什么需要调用 shell,而不是直接调用你的进程。
    • 我没有明确指出,但 perl 解释器可能会将其作为“system()”的一部分。
    • @xyld:您可以通过向system 传递多个参数来绕过shell。仅当您将命令作为单个字符串传递时,才会调用它来解析命令。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 2018-01-05
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多