7

我无法从在 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 正确启动长时间运行的进程而没有这些问题的建议将不胜感激!

4

3 回答 3

2

您可能想阅读讨论。除非您知道如何准备东西,否则似乎您不应该使用 mod_perl。您必须使用诸如Apache2::SubProcess之类的模块

于 2009-01-23T03:16:53.730 回答
1

尝试在分叉之前关闭您的 STDIN/STDOUT 句柄。

于 2009-01-23T02:38:35.007 回答
0

在我的(以前的 mod_perl,现在的 FCGI)代码中,我在“if ($kpid)”的“else”子句中,

    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;
}
于 2009-01-23T03:12:04.237 回答