如何使用perl杀死具有多个fork的进程

时间:2018-05-21 14:16:47

标签: perl

我有一个测试用例,其中多个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
.....
.....
.....

2 个答案:

答案 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 进程(主进程)。