Нет ошибки дочерних процессов в perl

У меня есть сценарий Perl, который вызывает sqldr и загружает данные в таблицу из плоского файла.

Теперь моя проблема в том, что хотя sqldr нормально загружает таблицу, он возвращает код выхода как -1 (полученный с помощью $?), когда я попытался использовать $!, он говорит No child processes.

Я выполняю этот скрипт с помощью команды sudo

sudo -u <uname> bash
<script_name>.pl

Этот Perl-скрипт работает нормально, если я запускаю его прямо из своего идентификатора пользователя. Я действительно не понимаю, почему эта ошибка появляется только тогда, когда я запускаю через пользователя sudo.

Пожалуйста, помогите мне понять эту ошибку.

РЕДАКТИРОВАТЬ: он работает нормально, если я даю $SIG{CHLD} = 'DEFAULT'; в своем коде. Но если я уберу этот шаг, проблема снова появится. Я получил этот код из WWW, когда просматривал эту ошибку. Есть идеи, что он делает?


person Vivek    schedule 09.04.2011    source источник
comment
Очень сложно диагностировать это, не видя хотя бы соответствующие части вашего кода Perl.   -  person crazyscot    schedule 09.04.2011
comment
Это 300 строк кода, и я действительно не знаю, в какой части кода возникает эта ошибка.   -  person Vivek    schedule 09.04.2011
comment
Может помочь документация Perl для wait().   -  person Andy    schedule 09.04.2011
comment
$! изменен для ошибок в текущем процессе.   -  person Horus    schedule 10.04.2011
comment
@Horus Можете ли вы предоставить более подробную информацию о том, что вы сказали?   -  person Vivek    schedule 11.04.2011
comment
Я имею в виду, что он запускает дочерний процесс и, похоже, хочет получить эту информацию об ошибке. $! переменная хранит только информацию об ошибке для текущего процесса, она никогда не будет хранить информацию для дочернего процесса. Информация об ошибках SQLLDR может быть собрана в текущем процессе несколькими способами, но не с помощью $!.   -  person Horus    schedule 11.04.2011
comment
Я знаю, что вы упомянули, что ваш код состоит из более чем 300 строк, но было бы полезно, если бы вы могли предоставить часть кода вокруг '$!' часть. Не могли бы вы указать хотя бы несколько строк до строки, в которой вы печатаете или умираете с помощью $!? Это было бы очень полезно, но, может быть, недостаточно, мы не узнаем, пока не увидим.   -  person wallisds    schedule 26.04.2011
comment
Я видел эту ошибку раньше... вы устанавливаете для $SIG{CHLD} значение 'IGNORE' в этом скрипте или устанавливаете его как таковое в родительском процессе. Проблема в том, что system использует waitpid (или его форму) для ожидания завершения вашей команды. Если вы игнорируете завершение дочернего процесса, то waitpid попытается получить уже исчезнувший дочерний процесс. Использование ожидания, когда у вас нет дочерних процессов, дает эту ошибку.   -  person unpythonic    schedule 07.06.2011


Ответы (1)


На большинстве платформ Unix сигнал CHLD (иногда также известный как CLD) имеет особое поведение по отношению к значению 'IGNORE'. Установка $SIG{CHLD} на 'IGNORE' на такой платформе приводит к тому, что процессы-зомби не создаются, когда родительский процесс не выполняет wait() своих дочерних процессов (т. е. дочерние процессы автоматически пожинаются). Вызов wait() с $SIG{CHLD}, установленным на 'IGNORE', обычно возвращает -1 на таких платформах.
Выдержка из http://perl.active-venture.com/pod/perlipc-signal.html

В основном происходит то, что где-то сигнал CHLD был установлен на IGNORE вероятно, sqlldr. Когда вы пытаетесь проверить статус дочернего процесса, вы получаете -1, который иногда называют ECHILD. Это происходит потому, что информация о статусе завершения дочернего процесса была отброшена из-за игнорирования сигнала CHLD. Установив $SIG{CHLD} = 'DEFAULT';, вы указываете, что сигнал CHLD должен обрабатываться обработчиком ПО УМОЛЧАНИЮ, а не игнорироваться.

Я не знаю, почему сигнал CHLD игнорируется, когда скрипт выполняется от пользователя sudo, а не выполняется непосредственно от вашего идентификатора пользователя.

person dave    schedule 09.06.2011