如果我有一个长期运行的system
命令就像apt-cache search <some query>
,有没有办法转发SIGINT
通过发送^C
在命令行上访问父 Perl 进程,这样所有子进程都会被收获。
此示例没有所需的行为。该信号被发送到子进程。
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use autodie;
# long running command on ubuntu, produces a ton of output.
# replace with your favorite long running command
system("apt-cache search hi");
print("Perl did not catch SIGINT even with autodie\n");
我尝试寻找捕获将由以下命令创建的孩子的 pid 的方法system("apt-cache search hi &")
,但找不到,所以我尝试了fork
ing and exec
处理进程并编写信号处理程序。这不起作用,因为apt-cache
本身通过以下方式启动一些进程clone
系统调用。手动滚动一些逻辑来遍历进程树的一部分并清理
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use autodie;
my $cpid;
$SIG{INT} = sub {
kill 'KILL', $cpid;
exit;
};
# long running command on ubuntu, produces a ton of output.
# replace with your favorite long running command
$cpid = fork;
if ($cpid == 0) {
exec 'apt-cache', 'search', 'hi';
}
print "Perl did not catch SIGINT even with autodie\n";
我想本质上我想要的是一种确定子进程是否由system
由于类似信号而退出SIGINT
所以我可以让 Perl 脚本自行清理,或者以一种方式遍历子进程并收获它们,从而干净、可移植地处理进程管理的奇怪边缘情况。
让子进程成为进程组的头,然后向整个进程组发送信号。
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use POSIX qw( setpgid );
my $child_pid;
$SIG{INT} = sub {
kill INT => -$child_pid if $child_pid;
exit(0x80 | 2); # 2 = SIGINT
};
my $child_pid = fork();
if (!$child_pid) {
setpgid($$);
exec 'apt-cache', 'search', 'hi';
}
WAIT: {
no autodie;
waitpid($child_pid, 0);
redo WAIT if $? == -1 and $!{EINTR};
die $! if $? == -1;
}
exit( ( $? >> 8 ) | ( 0x80 | ( $? & 0x7F ) ) );
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)