Wie gabeln ich richtig mit mod_perl2?
Frage
Ich habe Probleme, eine lang andauernde Forking von einigen Code-Prozess unter mod_perl2 läuft.
Alles funktioniert in den meisten Fällen, aber es scheint, dass der gegabelte Prozess offenes Handles zu Apache Logfiles hält - das bedeutet, Apache nicht neu starten, während der Prozess läuft (ich einen ‚failed Logfiles öffnen‘ Nachricht).
Hier ist der Code verwende ich:
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";
}
Zurück in den mod_perl1 Tagen, ich erinnere mit $r->cleanup_for_exec
dieses Problem zu lösen, aber es scheint nicht unter mod_perl2 unterstützt werden. (Edit: Anscheinend es nicht mehr erforderlich ist .. )
Jede Beratung, wie man richtig einen lang andauernder Prozess von mod_perl2 ohne diese Probleme beginnen wäre sehr dankbar!
Lösung
Sie wollen wahrscheinlich lesen diese Diskussion. Es scheint, dass Sie nicht auf mod_perl Gabel sollten, wenn Sie wissen, wie die Dinge vorzubereiten. Sie haben ein Modul verwenden, wie zum Beispiel Apache2 :: Subprocess
Andere Tipps
Versuchen Sie schließen Ihre STDIN / STDOUT Griffe vor der Gabel.
In meiner (früher mod_perl, jetzt FCGI) Code, ich habe in der "else" Klausel des "if ($ kpid)",
close STDIN;
close STDOUT;
close STDERR;
setsid();
Auch aus Gründen, die ich vergessen habe, habe ich sofort Gabel wieder, und dann in , die Kind wieder zu öffnen STDIN, STDOUT und STDERR.
So wie es aussieht:
$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;
}