Как правильно разветвляться с mod_perl2? - PullRequest
7 голосов
/ 23 января 2009

У меня проблемы с ветвлением долго выполняющегося процесса из некоторого кода, запущенного под mod_perl2.

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

Вот код, который я использую:

use POSIX; # required for setsid

# Do not wait for child processes to complete
$SIG{CHLD} = 'IGNORE';

# fork (and make sure we did!)
defined (my $kid = fork) or die "Cannot fork: $!\n";

if ($kid) {
    return (1, $kid);
}else {
    # chdir to /, stops the process from preventing an unmount
    chdir '/' or die "Can't chdir to /: $!";

    # dump our STDIN and STDOUT handles
    open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
    open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";

    # redirect for logging
    open STDERR, '>', $log_filename or die "Can't write to log: $!";

    # Prevent locking to apache process
    setsid or die "Can't start a new session: $!";

    # execute the command
    exec( $cmd, @args );

    die "Failed to exec";
}

В те времена, когда я работал с mod_perl1, я вспоминаю, как использовать $r->cleanup_for_exec для решения этой проблемы, но, похоже, он не поддерживается в mod_perl2. (Правка: Видимо больше не требуется ..)

Будем весьма благодарны за любые советы о том, как правильно запустить длительный процесс из mod_perl2 без этих проблем!

Ответы [ 3 ]

2 голосов
/ 23 января 2009

Вы, вероятно, хотите прочитать это обсуждение. Кажется, вы не должны разветвляться на mod_perl, если вы не знаете, как готовить вещи. Вы должны использовать такой модуль, как Apache2 :: SubProcess

1 голос
/ 23 января 2009

Попробуйте закрыть ручки STDIN / STDOUT перед вилкой.

0 голосов
/ 23 января 2009

В моем (ранее mod_perl, теперь FCGI) коде я в выражении "else" слова "if ($ kpid)",

    close STDIN;
    close STDOUT;
    close STDERR;
    setsid();

Кроме того, по причинам, которые я забыл, я немедленно снова разветвляюсь, а затем в , чтобы дочерний элемент снова открыл STDIN, STDOUT и STDERR.

Так это выглядит так:

$SIG{CHLD} = 'IGNORE';

# This should flush stdout.
my $ofh = select(STDOUT);$| = 1;select $ofh;

my $kpid = fork;
if ($kpid)
{
    # Parent process
    waitpid($kpid, 0);
}
else
{
    close STDIN;
    close STDOUT;
    close STDERR;
    setsid();
    my $gpid = fork;
    if (!$gpid)
    {
        open(STDIN, "</dev/null") ;#or print DEBUG2 "can't redirect stdin\n";
        open(STDOUT, ">/dev/null") ;#or print DEBUG2 "can't redirect stdout\n";
        open(STDERR, ">/dev/null") ;#or print DEBUG2 "can't redirect stderr\n";
        # Child process
        exec($pgm, @execargs) ;# or print DEBUG2 "exec failed\n";
    }
    exit 0;
}
...