2009-02-13 38 views
1

如果我有一个脚本是另一个程序的包装器(例如,a daemonizer wrappera wrapper for mathematica),在封装程序中捕获信号并将它们传递给子程序有时很有用。 例如,这里的一些Perl代码来处理INT(中断)信号,因此,如果您启动包装后做CTRL-C子程序也被中断:哪些信号应该将包装脚本传递给子程序?

my $subprogram = "foo args"; 
my $pid = open(F, "$subprogram |") or die "Can't open pipe from $subprogram: $!"; 
$SIG{INT} = sub { kill('INT', $pid); 
        close(F); 
        die "Passed along INT signal and now aborting.\n"; }; 
print while(<F>); 
close(F); 

[所有可能的信号]中( http://en.wikipedia.org/wiki/Signal_(computing)一个程序可以处理,哪些应包装脚本一起传递
还有什么,一个好的包装应该做

编辑:??本来这个问题是问如何相处的所有可能的信号传递感谢我得知的最初答案不是正确的问题。

编辑:我想出了什么扔我在这里循环。 Mathematica显然脱离了其父进程。所以,我必须沿着不同的终止信号传递明确:

$SIG{INT} = sub { kill('INT', $pid); }; # pass along SIGINT (eg, ctrl-C) 
$SIG{TERM} = sub { kill('TERM', $pid); }; # pass along SIGTERM (kill's default) 
$SIG{QUIT} = sub { kill('QUIT', $pid); }; # pass along SIGQUIT 
$SIG{ABRT} = sub { kill('ABRT', $pid); }; # pass along SIGABRT 
$SIG{HUP} = sub { kill('HUP', $pid); }; # pass along SIGHUP 

通常这不会是必要的,因为子进程自动获取这些信号一起传送(感谢那个让我直在这个问题的答案!)。所以现在我想知道为什么(以及如何)数学分离自己...

+0

你试图解决一个问题,你不应该试图解决无论如何,国际海事组织。看到我更新的答案。 – 2009-02-14 15:28:48

回答

2

有很多信号,这将是“危险”,通过这种方式“通过”。 “man 7 signal”,看看SIGPIPE,SIGILL,SIGCHILD等等。你很可能不想碰那些家伙。

所以,真正的问题是:你在找什么行为?我敢打赌,你真正想要的是SIGINT & SIGCONT被传递给孩子。子程序对HUP,USR1或USR2等其他信号是否有兴趣?

我认为你真的只对SIGINT &感兴趣,其余的(即SIGSEGV,SIGKILL等)会照顾好自己,因为父进程终止也会清理孩子。

哦,对了,你的例子:

print while(<F>); 

是好的,如果父perl的进程被挂起,它不会继续是F阅读,一旦管道填满,你的子程序将阻止写入标准输出,这可能与你想要的行为非常相似。

对于一些更有趣的想法,请看看“man bash”和“trap”内建,以了解shell开发人员为解决此问题所做的工作。

+0

很酷,谢谢!我不想假设任何关于子程序的事情 - 它可能会用信号做一些花哨的事情。那么这份清单应该包括INT,CONT,HUP,USR1,USR2吗?还要别的吗? – dreeves 2009-02-13 23:45:44

+0

所以,令人惊讶的是,在数学的情况下,由TERM,QUIT,ABRT或HUP进行的父进程终止不会导致数学结束,除非我明确地将它们传递给它们。现在我很好奇mathematica如何管理它! – dreeves 2009-02-14 09:00:10

2

我真的不明白你为什么想这样做。对于这一点,我不明白你为什么要发送信号到包装脚本。

ETA:停止并重新启动信号发送到整个过程组。如果这就是你所追求的:只要确保你的子进程是该进程组的一部分(这是默认的AFAIK)。

ETA2: 如果真的数学本身分离(可使用setsid()setpgid()来完成),这意味着它明确不希望收到此类信号,所以你不应该给他们:它可能不会处理它们无论如何。

+0

例如,如果我在运行“foo arg1 arg2”的cmd行上运行“wrapper.pl foo arg1 arg2”作为子程序,然后执行ctrl-C,我想让foo完全中断,就好像我已经运行了“foo arg1 arg2“。 (我会尝试将问题编辑得更清楚,或者让我知道如果我想到这个错误)。 – dreeves 2009-02-14 00:10:17

+0

除非您采取措施拆除您正在包装的过程,否则终端发送的信号将被发送至无论如何孩子进程。 – 2009-02-14 01:03:27

1

您可以通过keys %SIG获得所有信号的列表。因此,通过通过他们的,你设置处理程序发送信号的子进程ID:

for my $signal (keys %SIG) { 
    $SIG{$signal} = sub { kill($signal, $child_pid); }; 
} 

你可能会想本地化%SIG

不是我说这是一个好主意,但这是如何做到这一点。

2

无。

,你可能会在键盘产生的信号被发送反正给子进程,除非孩子采取措施,以避免(在这种情况下,你是谁干涉)。

可能杀死父进程的其他信号通常会导致孩子消失时,它旁边写当父去世已关闭管道。

所以,除非你有理由认为,子进程mismanages信号,我不会担心任何中继信号给孩子。如果孩子误解了信号,也许你应该修理孩子而不是破解父母。