我有一个测试用例,其中多个fork用于创建孙子,父进程处于无限循环中,我正在实现一个perl脚本来终止进程。目前它适用于单个fork()但不适用于多个fork():
TEST_CASE: $ cat loop.c
#include<stdio.h>
#include <sys/types.h>
#include<unistd.h>
void process_1()
{
fork();
fork();
fork();
if(fork() == 0)
{
printf( "G_Child1\n");
}else{
while(1){
printf("parent\n");
}
}
}
int main()
{
process_1();
return 0;
}
$ gcc loop.c -o loop.bin
PERL-SCRIPT:运行上述二进制文件的脚本。下面的脚本适用于一个fork()但不能使用多个fork():
$ cat timeout.pl
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
use Time::HiRes qw(sleep);
if(!defined( my $pid = fork())) {
die "Cannot fork a child: $!";
} elsif ($pid == 0) {
print "Printed by child process\n";
exec("./loop.bin");
} else {
print "Printed by parent process\n";
sleep(1);
my $ret = waitpid(-1, WNOHANG);
if ($ret == 0){
kill ('KILL',$pid);
sleep(1);
}
}
输出: $ perl timeout.pl
Printed by child process
G_Child1
parent
parent
parent
parent
parent
parent
parent
parent
.....
.....
.....
答案 0 :(得分:3)
在更复杂的情况下,您可以将perl子进程设置为带有POSIX::setsid()
的会话 leader ,然后将信号发送到进程将负值传递给kill
。
if(!defined( my $pid = fork())) {
die "Cannot fork a child: $!";
} elsif ($pid == 0) {
POSIX::setsid(); # make this process a session leader
print "Printed by child process\n";
system("./program_that_forks"); exit; # or exec('./program_that_forks')
} else {
...
kill('KILL', -$pid); # -$pid means signal the whole process group
...
}
如果program_that_forks
也通过调用setsid(1)
或关闭标准文件描述符并成为守护进程来操作进程组,则约定是程序将其进程ID写入文件,并为系统任务脚本读取此文件以通知程序(运行ls /var/run/*.pid
以查看一些示例)。
答案 1 :(得分:0)
我在 perl 测试中遇到了类似的问题,其中我分叉到一个运行新 Java 进程的子进程中,该子进程也有三个 Java 后代进程。所以我有:
Perl test process (filename.t)
- Perl fork
- Java (main)
- Java sub proc 1
- Java sub proc 2
- Java sub proc 3
解决方案是按升序杀死进程列表,从后代到祖先。实际上,Java 确实允许我杀死主进程,也会杀死其他三个子进程,但是杀死第二个 Perl 进程并不会停止下一个 Java 进程(主进程)。