杀死在infinte循环中运行system()函数的子进程在perl

时间:2018-05-21 11:30:14

标签: perl

我尝试过使用无限循环的简单程序,我使用PERL脚本运行它并在10次睡眠后尝试杀死它,但是我的程序没有杀死子进程并且在无限循环中运行。

// C代码:    $ cat loop.c

#include <stdio.h>
int main(){

while(1){
 printf("Infinite loop\n");
        }

return 0;
}


$ gcc loop.c -o loop.bin

// PERL CODE     $ 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";
   system("./loop.bin");
} else {
   print "Printed by parent process\n";
   sleep(10);
   my $ret = waitpid($pid, WNOHANG);

   if ($ret == 0){
     kill ('KILL',$pid);
         sleep(1);
         }
   }

// OUTPUT:执行后,perl脚本不会终止子进程(./TC_1.bin)     $ perl timeout.pl

Printed by child process
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
...
...
..

1 个答案:

答案 0 :(得分:5)

$pidfork调用创建的子进程的进程ID。这是一个perl进程。当您调用system($command)时,会创建一个新进程,运行命令$command,并且您不知道该命令的进程ID是什么。呼叫kill('KILL',$pid)会向后台perl进程发送一个信号,但不一定会向其子进程发送信号,因此您无法确定system呼叫是否也会收到该信号。

一种解决方案是使用exec代替system

...
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("./loop.bin");
} else {
...

execsystem类似,但它不是在新进程中启动命令,而是用运行命令的进程替换现有进程,保留进程ID。因此,在调用exec之后,子perl进程将消失,$pid将引用运行命令./loop.bin的进程。现在您可以发信号$pid,它将被发送到所需的过程。