如果我有一个脚本是另一个程序的包装器(例如,a daemonizer wrapper或a wrapper for mathematica),有时在包装器程序中捕获信号并将它们传递给子程序是有用的。 例如,这里有一些处理INT(中断)信号的Perl代码,这样如果你在启动包装后执行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),包装脚本应该传递哪些信号?
还有其他好包装应该做的吗?
$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
通常情况下这不是必需的,因为子进程会自动传递这些信号(感谢答案让我直截了当!)。所以现在我想知道为什么(以及如何)mathematica分离自己...
答案 0 :(得分:2)
有许多信号以这种方式“通过”是危险的。 “男人7信号”,看看像SIGPIPE,SIGILL,SIGCHILD等等。你很可能不想碰这些家伙。
所以,真正的问题是:你正在寻找什么样的行为?我打赌你真正想要的只是SIGINT&amp; SIGCONT将被传递给孩子。子程序是否与其他信号(如HUP,USR1或USR2)有什么关系?
我认为你真的只对SIGINT&amp; SIGCONT和其他人(即SIGSEGV,SIGKILL等)将自行处理,因为父进程终止也将清理孩子。
哦,顺便说一下,你的例子:
print while(<F>);
很好,如果父perl进程被暂停,它将不会继续从F读取,一旦该管道填满,你的子程序将阻止写入stdout,这可能也是你想要的行为。
对于一些更有趣的想法,请查看“man bash”和内置的“陷阱”,以了解shell开发人员为帮助解决此问题所做的工作。
答案 1 :(得分:2)
我真的不明白你为什么要那样做。就此而言,我不明白为什么要将信号发送到包装器脚本。
ETA:停止并重新启动信号被发送到整个进程组。如果这就是您所追求的:只需确保您的子进程是该进程组的一部分(默认为AFAIK)。
ETA2:
如果mathematica真正分离(可以使用setsid()
和setpgid()
完成),这意味着它明确地不想接收这样的信号,所以你不应该发送它们:它可能无法处理无论如何他们。
答案 2 :(得分:2)
无。
您可能会在键盘上生成的信号被发送到子进程,除非孩子采取措施避免这种情况(在这种情况下,您要干扰谁)。
可能会杀死父进程的其他信号通常会导致子进程在下次写入父进程死亡时关闭的管道时消失。
所以,除非你有理由认为儿童过程管理不善,否则我不担心将任何信号转发给孩子。如果孩子管理不善,也许你应该修理孩子而不是破坏父母。
答案 3 :(得分:1)
您可以使用keys %SIG
获取所有信号的列表。因此,要将它们全部传递,您可以设置处理程序以将信号发送到子进程ID:
for my $signal (keys %SIG) {
$SIG{$signal} = sub { kill($signal, $child_pid); };
}
您可能希望本地化%SIG
。
不是说我说这是个好主意,但那是怎么做的。