Как избежать зомби в скриптах Perl CGI, работающих под Apache 1.3? - PullRequest
7 голосов
/ 07 января 2010

Различные сценарии Perl (включая серверную часть) вызывают модуль Perl со многими функциями на веб-сайте. EDIT: Скрипты используют , используют lib для ссылки на библиотеки из папки. В периоды занятости скрипты (не библиотеки) становятся зомби и перегружают сервер.

Сервер перечисляет:

319 ?        Z      0:00 [scriptname1.pl] <defunct>    
320 ?        Z      0:00 [scriptname2.pl] <defunct>    
321 ?        Z      0:00 [scriptname3.pl] <defunct>

У меня есть сотни экземпляров каждого.

EDIT: Мы не используем fork, system или exec, кроме директивы SSI

<!--#exec cgi="/cgi-bin/scriptname.pl"-->

Насколько я знаю, в этом случае сам httpd будет владельцем процесса. MaxRequestPerChild имеет значение 0, что не должно позволить родителям умереть до завершения дочернего процесса.

До сих пор мы полагали, что временное приостановление работы некоторых из сценариев помогает серверу справиться с несуществующими процессами и предотвратить его падение, хотя процессы зомби все еще формируются без сомнения. По-видимому, gbacon кажется наиболее близким к истине с его теорией, что сервер не в состоянии справиться с нагрузкой.

Что может привести к отказу httpd от этих процессов? Есть ли лучшая практика, чтобы предотвратить это?

Спасибо

Ответ: Дело идет к Робу. По его словам, CGI-скрипты, которые генерируют SSI, не будут обрабатываться этими SSI. Оценка SSI происходит перед запуском CGI в цикле запросов Apache 1.3. Это было исправлено в Apache 2.0 и более поздних версиях, чтобы CGI могли генерировать команды SSI.

Поскольку мы работали на Apache 1.3, для каждого просмотра страницы SSI превращался в несуществующие процессы. Несмотря на то, что сервер пытался их очистить, он был слишком занят выполнением задач, чтобы иметь возможность выполнить их успешно. В результате сервер упал и перестал отвечать на запросы. В качестве краткосрочного решения мы рассмотрели все SSI и перенесли некоторые процессы на клиентскую сторону, чтобы освободить ресурсы сервера и дать ему время для очистки. Позже мы обновились до Apache 2.2.

Ответы [ 3 ]

7 голосов
/ 07 января 2010

Больше лейкопластыря, чем лучшая практика, но иногда вы можете сойти с рук простым

$SIG{CHLD} = "IGNORE";

Согласно документации perlipc

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

Если вам небезразличны состояния выхода дочерних процессов, вам необходимо собрать их (обычно называемые «пожинанием»), позвонив по номеру wait или waitpid. Несмотря на жуткое имя, зомби - это просто дочерний процесс, который завершился, но статус которого еще не получен.

Если ваши Perl-программы сами являются дочерними процессами, превращающимися в зомби, это означает, что их родители (те, кто забывает и забывает ваш код) должны убирать за собой. Процесс не может остановить себя от превращения в зомби.

2 голосов
/ 08 января 2010

Я только что увидел ваш комментарий о том, что вы используете Apache 1.3, и это может быть связано с вашей проблемой.

SSI могут запускать CGI. Но сценарии CGI, которые генерируют SSI, не будут обрабатываться этими SSI. Оценка SSI происходит перед запуском CGI в цикле запросов Apache 1.3. Это было исправлено в Apache 2.0 и более поздних версиях, чтобы CGI могли генерировать команды SSI.

Как я уже говорил выше, попробуйте запустить ваши скрипты самостоятельно и посмотрите на результат. Они генерируют SSI?

Редактировать: Вы пытались запустить тривиальный сценарий Perl CGI, чтобы просто распечатать HTTP-ответ типа Hello World?

Тогда, если это работает, добавьте тривиальные директивы SSI, такие как

<!--#printenv -->

и посмотрим, что произойдет.

Редактировать 2: Просто понял, что, вероятно, происходит. Зомби появляются, когда дочерний процесс завершается и не пожинается. Эти процессы торчат и медленно расходуют ресурсы в таблице процессов. Процесс без родителя является потерянным процессом.

Вы отключаете процессы внутри своего Perl-скрипта? Если да, вы добавили вызов waitpid () к родителю?

У вас также есть правильный выход из скрипта?

CORE::exit(0);
0 голосов
/ 07 января 2010

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

Показывает ли листинг ps чрезмерное количество экземпляров одного конкретного запущенного скрипта?

Используете ли вы CGI, использующие mod_perl?

Редактировать: Только что видел ваши комментарии по поводу SSI. Не забывайте, что директивы SSI сами могут запускать сценарии Perl. Посмотрите, что CGI пытается запустить?

Они зависят от еще одного сервера или службы?

...