perl – 使用系统时信号传播到父级
我编写了一个包装器脚本,使用system()启动另一个脚本.子脚本捕获SIGINT并在内部处理异常.因此,它不应该在退出时将SIGINT传播给它的父级.但是,在某些情况下,父级仍然会收到SIGINT.例如(parent.pl):
use feature qw(say); use strict; use warnings; use POSIX (); my @data = (q(child.pl 'dummy'),q(child.pl),q(bash -c child.pl),q(sh -c child.pl)); for ( @data ) { say "Running command '$_'.."; my $res = system $_; my $signal = $res & 127; my $rval = $res >> 8; say "Parent received return value: $rval"; if ( $signal == POSIX::SIGINT ) { say "Parent received SIGINT"; } } 和child.pl: use feature qw(say); use strict; use warnings; eval { local $SIG{INT} = sub { die "Aborted by user.n" }; sleep 10; }; if ( $@ ) { print "n" . $@; exit 0; } say "Timed out.."; exit 1; 如果我在超时前按CTRL-C,输出如下: Running command 'child.pl 'dummy''.. ^C Aborted by user. Parent received return value: 0 Parent received SIGINT Running command 'child.pl'.. ^C Aborted by user. Parent received return value: 0 Running command 'bash -c child.pl'.. ^C Aborted by user. Parent received return value: 0 Running command 'sh -c child.pl'.. ^C Aborted by user. Parent received return value: 0 Parent received SIGINT 因此,在第一种情况和最后一种情况下,父节点接收SIGINT,而对于第二种和第三种情况,它不接收SIGINT. 这是什么原因?如何修复以使SIGINT不会传播给第一个和最后一个案例? (我怀疑它与Shell的类型有关,即sh vs bash) 解决方法
首先,让我们知道正在执行的内容.
system($shell_command) 是的缩写 system({ "/bin/sh" } "/bin/sh","-c",$shell_command) 除非shell命令不包含shell元字符,但在这种情况下不包含空格 system($shell_command) 是的缩写 my @cmd = split(' ',$shell_command); system({ $cmd[0] } @cmd) 因此, system("child.pl 'dummy'") is short for system({ "/bin/sh" } "/bin/sh","child.pl 'dummy'") system("child.pl") is short for system({ "child.pl" } "child.pl") system("bash -c child.pl") is short for system({ "bash" } "bash","child.pl") system("sh -c child.pl") is short for system({ "sh" } "sh","child.pl") 值得注意的是,bash将自己替换为child.pl,而不是在此特定情况下在单独的进程中生成它.这使得child.pl在第三种情况下成为parent.pl的直接子项(就像第二种情况一样). 其次,让我们知道Ctrl-C的作用. 按下Ctrl-C时,终端将SIGINT发送到以该终端为控制终端的每个进程.换句话说,SIGINT被发送到会话的每个进程. 通过添加系统可以看到(“ps -o pid,ppid,pgrp,sid,cmd”);到child.pl,我们的会话中有三到四个进程,具体取决于测试用例. > child.pl:child.pl处理SIGINT.它没有被它杀死. 所以,这就是你所观察到的: >当parent.pl的(直接)子节点是child.pl [测试用例2和3]时,子节点(child.pl)不会死于SIGINT,因为它处理SIGINT.>当parent.pl的(直接)子节点是shell [测试用例1和4]时,子节点(shell)从SIGINT消失,因为非交互式shell不处理/忽略SIGINT. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |