ForkManager SIGINT only kills the current process in fork

I want all child processes to die when I kill a perl process using ForkManager. In the code below, if I run it and press ctrl+ cwhile the wait line is executing, the sleep process will be killed, but the lines print

will execute concurrently until the script ends. Ideally, I would like the interrupt to stop executing immediately. What can I do?

#!/usr/bin/perl -w
use Parallel::ForkManager;

main {
    my $fork1 = new Parallel::ForkManager(8);
    while (1) {
        $fork1->start and next;
        system("sleep 15s");
        print "Still going!"
        $fork1->finish;
    }
    fork1->wait_all_children;
}

      

+3


source to share


2 answers


First, the use system

means you might have something weird because ... then you are allowing whatever you call to do things to handle signals on their own.

This could be your problem.

However, otherwise, what you can do with perl

is configuration signal handlers - what to do if a signal is received by this process. By default - signals are either set to "exit" or "ignore".

You can see it is currently through print Dumper \%SIG;



However, the simplest solution to your problem, I think, would be to set up a hook handler SIGINT

and then send kill

to your current process group.

The behavior of kill when the PROCESS number is zero or negative depends on the operating system. For example, on POSIX systems, zero will signal the current process group, -1 will signal all processes, and any other negative PROCESS number will act as a negative signal number and kill the entire specified process group.

$SIG{'INT'} = sub { 
    kill ( 'TERM', -$$ );
};

      

+2


source


According to perldoc system

it system

actually ignores both SIGINT and SIGQUIT:

Since SIGINT and SIGQUIT are ignored at runtime, if you expect your program to terminate when these signals are received, you will need to do it yourself based on the return value.

So, if you want your processes to stop running if you SIGINT during a call system

, you need to implement this logic yourself:



#!/usr/bin/perl -w
use Parallel::ForkManager;

main {
   my $fork1 = new Parallel::ForkManager(8);
   while (1) {
      $fork1->start and next;
      print "Sleeping...";
      system("sleep 15s") == 0 or exit($?);
      print "Still going!";
      $fork1->finish;
   }
   fork1->wait_all_children;
}

      

OR a smarter approach is to use embedded Perl sleep

:

#!/usr/bin/perl -w
use Parallel::ForkManager;

main {
   my $fork1 = new Parallel::ForkManager(8);
   while (1) {
      $fork1->start and next;
      print "Sleeping...";
      sleep 15;
      print "Still going!";
      $fork1->finish;
   }
   fork1->wait_all_children;
}

      

+6


source







All Articles