2009-01-23 64 views
7

我無法從運行在mod_perl2下的一些代碼中分離長時間運行的進程。如何正確使用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得到支持。 (編輯:Apparently它不再需要..)

任何關於如何正確啓動從mod_perl2長期運行的進程沒有這些問題將不勝感激!

+0

嗨丹,你是如何解決這個問題的,我面臨同樣的問題。早些時候,我使用mod_perl1和`$ r-> cleanup_for_exec`工作正常,但在mod_perl2這不再需要,所以你可以幫我實現這個mod_perl2?提前致謝。 – 2013-06-14 10:29:55

回答

2

你可能想閱讀this討論。看來你不應該在mod_perl上分叉,除非你知道如何準備東西。你必須使用一個模塊,如Apache2::SubProcess

1

嘗試在分叉之前關閉STDIN/STDOUT手柄。

+0

這會完全破壞Apache ..父進程仍然必須爲客戶端產生響應(並通過STDOUT發送)。 – Dan 2009-01-23 02:41:46

0

在我(以前的mod_perl,現在FCGI)的代碼,我的 「如果($ 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; 
}