Wednesday, February 2, 2011

Perl: How to terminate a child process after a specified amount of time

There are times when I wanna kill a process that is taking too much time. Unfortunately Perl does not offer a direct method to terminate a spawned process after a specified time interval.

So, how can I kill Bill?!?

The script is as simple as the following:

#!/usr/bin/perl
use strict;

my $self;

# Maximum execution time (in sec) of the child process. When that timer expires, we send a kill command to the child process
my $MAX_EXEC_TIME = 10;

eval {
 # When the alarm interrupt is triggered, send the timed out\n message to the die function
 local $SIG{'ALRM'} = sub { die "timed out\n" };

 # Set ALARM to interrupt after MAX_EXEC_TIME seconds
 alarm($MAX_EXEC_TIME);

 print "Starting process bill.pl\n";

 # Start child process in asynch mode and get the child process id
 $self->{PID} = system 1, "perl bill.pl";
 print "Child Pid = $self->{PID}\n";

 # Wait for the child to terminate. If it ends before the ALARM is triggered, the process continues from *SECTION1*
 waitpid $self->{PID}, 0;

};

if ($@) {

 if ($@ eq "timed out\n") {

  # *SECTION2* The child process didn't return within the MAX_EXEC_TIME, let's kill it

  print "I timed out and killed pid $self->{PID}\n"; 

  if ($self->{PID})

  {

   # Send a SIGTERM message to let the process try to exit cleanly 
   kill(15,$self->{PID});
  }
  $self->{PID} = undef;
 }

 else {

  print "something else happened: $@\n";

 }

}

else {

 # *SECTION1* The child process terminated before the ALARM interrupt was triggered

 print "Child process terminated as expected. I can keep going...\n";

}

...and our Bill process is a simple infinite loop:
#!/usr/bin/perl



while(1) {

print "alive\n";

sleep(2);

}

No comments:

Post a Comment