2010-07-14 81 views
7

这是怎么回事?我认为SIGINT将被发送到前台进程组。为什么SIGINT在这里被抓到?

(我想,也许,该系统()正在运行一个外壳,其子进程创建一个新的进程组?任何人都可以证实这一点?)

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

然后按ctrl + d,然后按Ctrl + c,并注意“捕获的信号”从不打印。

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

这怎么能解决? (我已经测试了使用fork()的直接和明白,这个工程......这是不是一个可以接受的解决方案,在这个时候)

UPDATE:请注意,这有什么做“沉睡”只有命令需要一些任意长的时间才能运行,这比perl周围的命令要多得多。那么按下ctrl + c会被发送到命令(就像在前台进程组中那样),并以某种方式设法永远不会发送给perl。

回答

4

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; 
} 

或者,你可以检查的$与W *(价值{^ CHILD_ERROR_NATIVE})从POSIX模块

+3

methinks我需要再次阅读文档: - /谢谢。 – dlamotte 2010-07-14 16:36:40

+1

我想补充一点,你需要检查孩子的返回值的原因是你的shell将^ c/INT传递给整个进程组,给perl和儿童,在这种情况下,终止你的孩子的“睡眠10”。如果你简单地'从另一个shell中'kill -INT $ perl_pid',perl将很高兴SIG_IGNore你。 – pilcrow 2010-07-14 16:49:14

0

我不太明白你试图在这里实现什么...但你尝试简单地比较:

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

你能解释一下你想要去什么样的影响,以及你为什么调用shell?你能直接调用外部程序而不涉及shell吗?

+0

请参阅我的更新部分中呼吁, “沉睡” 无关与它做...它只是一个任意进程的占位符。它可以很容易地与“grep东西”切换,这将永远挂起,因为它期待从标准输入读取数据。 – dlamotte 2010-07-14 16:30:50

+0

@xyld:我意识到睡眠是一个占位符。我问你为什么需要调用shell,而不是直接调用你的过程。 – Ether 2010-07-14 17:06:48

+0

我并不明确,但是perl解释器可能会将它作为“system()”的一部分来执行。 – dlamotte 2010-07-15 15:48:30