3

I am using the Thread::Pool module in perl to parallelize some perl code. This process takes a while and occasionally I will kill it from the command line with a SIGINT. Doing so causes the program to end abruptly, as I expected. This leaves some messy temporary files around, so I'd like to install a signal handler. I did this:

sub INT_Handler{
    #clean up code
    exit(1);
}
$SIG{'INT'} = 'INT_handler';

before creating the thread pool and starting the threads. Now when I send the SIGINT, the worker threads that are running die, but the pool promptly launches another set workers to handle the next set of jobs and continues running. Why doesn't the call to exit in the signal handler exit the main thread? What do I need to stop the process from running?

Edited in response to mob's comment

** Further edit **

Here is an example I wrote up.

use Thread::Pool;

sub INT_handler{
    print "Handler\n";
    exit(1);
}

$SIG{'INT'}='INT_handler';

sub f{
    print "Started a thread " . rand(10000) . "\n";
    sleep(10);
}

my $pool;
my $submit = \&f;

if (0){
 $pool = Thread::Pool->new({do=>'f', workers=>5});
  $submit = sub{ $pool->job; }
}

for (my $i = 0; $i < 100; $i++){ $submit->(); }

$pool->shutdown if defined $pool;

with 0, I see the expected result

h:57 Sep 15 16:15:19> perl tp.pl
Started a thread 3224.83224635111
Handler

but with 1, this happens

h:57 Sep 15 16:14:56> perl tp.pl
Started a thread 5034.63673711853
Started a thread 9300.99967009486
Started a thread 1394.45532885478
Started a thread 3356.0428193687
Started a thread 1424.4741558014

etc and the handler doesn't get entered and the process continues running. I had to kill the process with a signal other than SIGINT. Without the handler, both cases simply exit when passed a SIGINT.

pythonic metaphor
  • 10,296
  • 18
  • 68
  • 110
  • 1
    This is in contention with [the documentation](http://search.cpan.org/perldoc?threads#BUGS_AND_LIMITATIONS): "Signals are *caught* by the main thread (thread ID = 0) of a script." Can you isolate and post some code where the signals seem to be caught in the worker threads? – mob Sep 15 '11 at 18:56
  • @mob Ok, so I must be mistaken that the signal is caught by the worker. I assumed that was the case because I explicitly call exit in the signal handler. Yet, what I observe are the worker threads that were running dying and a new set of workers being launched. – pythonic metaphor Sep 15 '11 at 19:42

1 Answers1

4

This is more a hint rather than a definitive answer, but it appears your main thread is never in the "safe" state to run the signal handler. It does work when you enable Perl's unsafe signals:

PERL_SIGNALS=unsafe perl tp.pl

See perlipc for more information on safe and unsafe signals -- maybe it will lead you in the right direction to implement it with safe signals (as it probably should be).


(update by mob) Building on Michal's original insight, this workaround with Perl::Unsafe::Signals also gets the handler to work as you'd expect
use Perl::Unsafe::Signals;
...
UNSAFE_SIGNALS {
    $pool->shutdown if defined $pool;
};

So clearly it is something about Perl's safe signalling mechanism that is interfering with the signal on its way to the handler. I wonder if this would be fixed by putting an UNSAFE_SIGNALS { ... } block inside of Thread::Pool::shutdown. Either way, I would file a bug report about this.

mob
  • 117,087
  • 18
  • 149
  • 283
  • I tried added `$ENV{PERL_SIGNALS} = "unsafe";` at the top of my example, but I still had the same problem. However, if I set the environment variable before running the script, it did work. Why is that? – pythonic metaphor Sep 16 '11 at 13:56
  • 1
    The variable is probably evaluated only when perl starts executing your script, so setting it in the script is too late. – Michał Wojciechowski Sep 16 '11 at 14:06
  • 1
    I found a thread [here](http://groups.google.com/group/perl.perl5.porters/browse_thread/thread/7cd25dcb2661ed67/3eeb441f1ce3e959?lnk=raot) where someone complains that internal setting of `PERL_SIGNALS` stopped working in 5.14 while he'd been happily using it until then. I'm using 5.8.8! Nonetheless, I'll probably install `Perl::Unsafe::Signals`. – pythonic metaphor Sep 16 '11 at 15:13