Perl: создание зомби через open () без close () - PullRequest
3 голосов
/ 15 декабря 2010

Вот проблема: У меня есть демон, который получает запросы от клиента, выполняет функцию (из некоторого модуля) из-за запроса и возвращает ответ клиенту. После форка () я закрываю STDIN, STDOUT и STDERR. Одной из функций является проверка dmesg. Для этого я получаю вывод dmesg через открыть (DMESG, "/ bin / dmesg |"). Я не закрываю этот fh после чтения из него, потому что я думал, что он закроется автоматически после завершения функции. Но этого не происходит, и я получаю зомби за каждый вызов dmesg.

Вкл. Как я могу заново инициализировать Perl STDIN / STDOUT / STDERR? Я обнаружил, что «проблема с закрытием STDOUT вместо повторного открытия заключается в том, что если вы откроете другие файлы, они могут получить fd 0,1 или 2 - мешает вам снова открыть STDOUT в будущем. " от jmanning2k И я думаю, что это как-то связано с этим, но я не совсем понимаю. Я надеюсь, что кто-то сможет мне это объяснить.

Я знаю, что могу избежать проблемы, например, вызывая dmesg через qx (); или просто закрытие fh, но я хочу понять, откуда появляются зомби.

Ответы [ 3 ]

7 голосов
/ 15 декабря 2010

Форма

open DMESG, "/bin/dmesg|";

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

Если вместо этого вы используете форму

open my $dmesg, "/bin/dmesg|";

лексическая переменная файлового дескриптора $dmesg будет закрыта при выходе из области видимости, при условии, что нет других причин поддерживать ее (т. Е. Она не передается обратно или не сохраняется в глобальной переменной).

6 голосов
/ 15 декабря 2010

open(DMESG, "/bin/dmesg |") Я не закрываю этот fh после прочтения, потому что я думал, что он автоматически закроется после завершения функции.

Чтобы это работало, ручка должна быть лексической, чтобы она могла правильно выпасть из области видимости.

open my $dmesg, …
1 голос
/ 15 декабря 2010

Проблема связана с тем, как реализован Perl. Вот фрагмент кода из функции Perl_do_openn в файле doio.c:

fd = PerlIO_fileno(IoIFP(io));
if (IoTYPE(io) == IoTYPE_STD) {
    /* This is a clone of one of STD* handles */
    result = 0;
}
else if (fd >= 0 && fd <= PL_maxsysfd) {
    /* This is one of the original STD* handles */
    saveifp  = IoIFP(io);
    saveofp  = IoOFP(io);
    savetype = IoTYPE(io);
    savefd   = fd;
    result   = 0;
}

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

...