如何正确使用mod_perl2分叉?

如何正确使用mod_perl2分叉?,perl,mod-perl2,Perl,Mod Perl2,我很难从mod_perl2下运行的一些代码中派生出一个长时间运行的进程 大部分情况下,一切都正常工作,但分叉进程似乎持有Apache日志文件的开放句柄——这意味着在进程运行时Apache不会重新启动,因为我收到一条“无法打开日志文件”消息 以下是我使用的代码: use POSIX; # required for setsid # Do not wait for child processes to complete $SIG{CHLD} = 'IGNORE'; # fork (and mak

我很难从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正确启动长时间运行的流程而不出现这些问题的建议都将不胜感激

尝试在fork之前关闭STDIN/STDOUT句柄。

在我以前的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;
}

您可能想阅读讨论。除非您知道如何准备东西,否则您不应该使用mod_perl。您必须使用像

这样的模块,这将彻底破坏Apache。。父进程仍然必须生成响应并通过STDOUT为客户端发送。父进程可以在分叉之前发送其响应;除非你在分叉之后在父母身上做了更多的工作。如果日志文件不在STDIN/OUT/ERR描述符上,您可以开始关闭在子进程中找到的任何大于2的打开描述符。是的,问题是apache进程在完成此请求后继续服务其他请求,杀死它的STDERR会中断其日志记录,我怀疑杀死它的STDIN会阻止它与父进程通信。不管怎样,我试过了,但没有解决问题;尝试在子进程中从3循环到1024,执行“open$fh,是的,您必须分叉两次,一次在setID之前创建新进程,另一次在setID之后确保您的会话和进程组没有引导进程。Hi Dan,您是如何解决此问题的,我面临着同样的问题。早些时候,我使用mod_perl1和$r->cleanup_for_exec运行良好,但在mod_perl2中,这不再是必需的,所以您可以帮助我在mod_perl2中实现这一点吗?提前谢谢。