Threaded perl and signal handlers

混江龙づ霸主 提交于 2019-12-12 09:54:46

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/7435539/threaded-perl-and-signal-handlers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!