Сообщение об ошибке «Сигнал SIGCHLD получен, но не установлен обработчик сигнала». - PullRequest
4 голосов
/ 16 марта 2020

Я пытаюсь отладить сложное приложение Perl, которое заканчивается сообщением об ошибке «Сигнал SIGCHLD получен, но обработчик сигнала не установлен». Я знаю, что он исходит из самого интерпретатора Perl, в частности из файла mg.c, и его невозможно перехватить. Но я не понимаю точную природу этого.

Является ли это внутренней ошибкой в ​​интерпретаторе типа "не должно происходить"?

Или есть (простой) способ воспроизвести эту ошибку с последними Perl версиями?

Я уже пытался воспроизвести ее с подсказками, указанными в https://lists.gnu.org/archive/html/bug-parallel/2016-10/msg00000.html, устанавливая и отключая обработчик сигнала в бесконечном l oop и постоянно подает этот сигнал и бесконечно l oop из другого сценария. Но я не смог воспроизвести описанное там поведение с Perl версиями 5.18.4, 5.26.0, 5.26.2, 5.28.2 и 5.30.2.

Я также обнаружил Сигнал SIGSTOP получен, но обработчик сигнала не установлен в perl script , где кто-то назначил $SIG{SIGSTOP} вместо $SIG{STOP}, но это также не помогает сделать проблему воспроизводимой с помощью простого сценария.

Все из тестов, которые я тестировал, был построен без поддержки потоков :

$ perl -Mthreads
This Perl not built to support threads
Compilation failed in require.
BEGIN failed--compilation aborted.

Ответы [ 2 ]

2 голосов
/ 19 марта 2020

Я отвечаю на свой вопрос здесь (насколько мне известно на сегодняшний день):

Ошибка исчезла, если вставить эти две строки:

$SIG{CHLD} ||= 'DEFAULT';
$SIG{HUP} ||= 'DEFAULT';

Я бы не назвал это исправление, а скорее обходной путь, потому что значение «ПО УМОЛЧАНИЮ» должно вызывать то же поведение, что и отсутствие значения, соответственно undef.

Сообщение об ошибке является внутренней ошибкой Perl. Интерпретатор выручает здесь в качестве защиты от ошибок обработки сигналов в Perl.

При этом нет простого примера, который воспроизводит ошибку. И если бы он был, это было бы ошибкой в ​​Perl.

Подобная ошибка сообщалась для параллельной GNU некоторое время a go: https://lists.gnu.org/archive/html/bug-parallel/2016-10/msg00000.html

Обнаруженная ошибка имеет несколько общих черт с ошибкой, с которой я столкнулся, а именно: она произошла после fork() ing.

Мое приложение - это сервер, основанный на Net::Server, и ошибка происходит, когда обработчик запроса порождает дочерний процесс. Интересно, что сообщение об ошибке (и выход) происходит за до , когда дочерний процесс завершается.

Дочерний процесс может потенциально выполняться очень долго. Поэтому он становится лидером сеанса с setsid(), все открытые дескрипторы файлов закрываются, и стандартный ввод перенаправляется на /dev/null до вызова exec(). Другими словами, это своего рода демонизация.

Следует также отметить, что ошибка исчезает при выполнении небольших изменений в коде, например, при сбросе содержимого %SIG для целей отладки.

Ошибка также не возникла, с Perl версиями 5.8.9, 5.14.4 и 5.16.3. С 5.18.4, 5.26.2 и 5.30.2 его всегда можно воспроизвести. Все эти исполняемые файлы были созданы без поддержки потоков интерпретатора.

0 голосов
/ 16 марта 2020

Сообщение «но не установлен обработчик сигнала» относится только к потокам, и обработка сигналов внутри потоков работает иначе, чем в вашем основном процессе.

Основной процесс может получать сигнал из любого количества мест - вызов kill в программе, вызов kill из другой программы Perl из операционной системы, из команды /usr/bin/kill из командной строки и т. д. c. Perl имеет обработчики сигналов «по умолчанию» для всех сигналов, которые могут быть отправлены из вашей системы. Вы можете перехватить некоторые из них, настроив обработчики в глобальной переменной %SIG, хотя некоторые сигналы (особенно SIGKILL и SIGSTOP) не могут быть перехвачены вашей программой.

Сигналы внутри потоков являются эмуляцией сигналов в вашей родительской операционной системе. Они могут быть отправлены только по телефону threads::kill, что означает, что на них можно сигнализировать только из вашей Perl программы. Perl не не устанавливает какие-либо обработчики сигналов по умолчанию для сигналов потока и предупреждает вас, когда потоку передается необработанный сигнал. И, в отличие от обычного набора сигналов, вы можете отключить сигналы KILL и STOP для потоков.

Чтобы защитить себя, установите обработчик сигналов для всех сигналов. Может быть что-то вроде:

use Carp;

sub thr_signal_handler {
    Carp::cluck("Received SIG$_[0] in ",threads->tid(),"\n";
}

# inside thread initialization function
$SIG{$_} = \&thr_signal_handler for keys %SIG;
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...