Обработчики Perl и сигналов с резьбой - PullRequest
3 голосов
/ 15 сентября 2011

Я использую модуль Thread::Pool в perl для распараллеливания некоторого кода perl. Этот процесс занимает некоторое время, и иногда я убиваю его из командной строки с помощью SIGINT. Это приводит к внезапному завершению программы, как я и ожидал. Это оставляет некоторые грязные временные файлы, поэтому я хотел бы установить обработчик сигнала. Я сделал это:

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

перед созданием пула потоков и запуском потоков. Теперь, когда я отправляю SIGINT, рабочие потоки , которые работают, умирают, но пул немедленно запускает другой набор рабочих для обработки следующего набора заданий и продолжает работать. Почему вызов для выхода в обработчике сигнала не выходит из основного потока? Что мне нужно, чтобы остановить запуск процесса?

Отредактировано в ответ на комментарий моба

** Дальнейшее редактирование **

Вот пример, который я написал.

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;

с 0, я вижу ожидаемый результат

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

но с 1 это происходит

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

и т. Д., И обработчик не вводится, и процесс продолжается. Мне пришлось убить процесс с помощью сигнала, отличного от SIGINT. Без обработчика оба случая просто завершаются, когда переданы SIGINT.

1 Ответ

4 голосов
/ 16 сентября 2011

Это скорее подсказка, чем окончательный ответ, но кажется, что ваш главный поток никогда не находится в «безопасном» состоянии для запуска обработчика сигнала. Это работает, когда вы включаете небезопасные сигналы Perl:

PERL_SIGNALS=unsafe perl tp.pl

См. perlipc для получения дополнительной информации о безопасных и небезопасных сигналах - возможно, это приведет вас в правильном направлении для реализации его с безопасными сигналами (как, вероятно, должно быть).


(обновление от моба) Основываясь на оригинальном понимании Михала, этот обходной путь с Perl::Unsafe::Signals также заставляет обработчик работать так, как вы ожидаете
use Perl::Unsafe::Signals;
...
UNSAFE_SIGNALS {
    $pool->shutdown if defined $pool;
};

Совершенно очевидно, что что-то в безопасном сигнальном механизме Perl мешает сигналу на пути к обработчику. Интересно, можно ли это исправить, поместив блок UNSAFE_SIGNALS { ... } внутрь Thread::Pool::shutdown. В любом случае, я бы подал отчет об ошибке об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...