Популярная демонология
Oct. 1st, 2014 10:09 pmЛекция по информатике.
Лектор: ... приложения, работающие в бэкграунде, они же...
Из аудитории: Демоны!
Лектор: Господь с тобой! Демоны...
(эпиграф взят на http://bash.im/ )
1. Когда демон хочет послать пару имейлов, каждый имейл должен посылаться в отдельном потоке, чтобы демон мог спокойно творить свое демоническое дело, не дожидаясь, пока мыло отправится. На первый взгляд, все довольно просто:
sub SendMessageInNewProcess
{
my $NewChild=fork(); # create a child process}
if ($NewChild) { return }; # return if parent, stay if child
#....... (all necessary code to send an email)
exit(0); # kill child process
Далее вызываем процедуру хоть десять раз. Однако не все оказалось так просто. Детки-то не дохнут, а остаются в памяти с пометкой defunct, то есть зомби. Как же их убить?
2. Хочу уметь самым простым способом запускать из веб-браузера независимый процесс. То есть браузер говорит "страница полностью загружена", а процесс все еще работает. Браузер можно вообще закрыть, но процесс на сервере будет как ни в чем ни бывало работать. Что-то никак не получалось. Если браузер мог дождаться окончания процесса, то страница грузилась и грузилась, пока процесс наконец не завершится. А если это демон, который завершиться не должен, а должен загрузиться и так и остаться, то демон-то загружался, а вот браузер пыжился, а потом выдавал уродливый таймаут. Что делать? Фактически тут целых две задачи:
2а. Запустить из браузера демон
2б. Запустить процесс, который поработает еще пару секунд (минут) после того, как браузер закончит загрузку страницы
В итоге все, конечно, разрешилось. Если речь идет о таком древнем языке, как PERL, то все твои проблемы уже у кого-нибудь лет десять назад возникали и на форумах разжеваны. В частности, почти все нюансы, относящиеся ко всему вышеперечисленному, разжевываются тут:
Improving mod_perl Sites' Performance: Part 6
http://www.perl.com/pub/2003/01/07/mod_perl.html
Не могу не процитировать наиболее живописные фрагменты. Это просто готический роман:
A zombie is a process that doesn't have a parent. When the child quits, it reports the termination to its parent. If no parent wait()s to collect the exit status of the child, then it gets "confused" and becomes a ghost process. This process can be seen as a process, but not killed.
[...]
Generally, the ps(1) utility displays these processes with the
[...]
The simplest solution is to ignore your dead children.
[...]
The $SIG{CHLD} = 'IGNORE'; statement protects us from zombies, as explained above. Another, more portable but slightly more expensive solution, is to use a double fork approach.