2009-01-23 28 views
7

Tengo problemas para realizar un proceso de larga ejecución a partir de algún código que se ejecute en mod_perl2.¿Cómo se tenedor correctamente con mod_perl2?

Todo funciona en su mayor parte, pero parece que el proceso bifurcado mantiene asas abiertas a los archivos de registro de Apache, esto significa que Apache no se reiniciará mientras se ejecuta el proceso (recibo un mensaje de error al abrir archivos de registro) .

Aquí está el código que estoy usando:

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"; 
} 

En los días mod_perl1, recuerdo usando $r->cleanup_for_exec para resolver este problema, pero no parece ser apoyado bajo mod_perl2. (Editar: Apparently ya no es necesario ...)

¡Cualquier consejo sobre cómo iniciar correctamente un proceso de larga duración desde mod_perl2 sin estos problemas sería muy apreciado!

+0

Hola Dan, cómo resolviste este problema, estoy enfrentando el mismo problema. Anteriormente estaba usando mod_perl1 y '$ r-> cleanup_for_exec' funcionaba bien, pero en mod_perl2 esto ya no es necesario, así que ¿podría ayudarme a implementar esto en mod_perl2? Gracias por adelantado. –

Respuesta

2

Es posible que desee leer this discusión. Parece que no deberías mantenerte mod_perl a menos que sepas cómo preparar las cosas. Tienes que usar un módulo como Apache2::SubProcess

1

Intente cerrar sus mangos STDIN/STDOUT antes de la horquilla.

+0

Eso rompería por completo Apache .. El proceso principal todavía tiene que producir una respuesta (y enviarla a través de STDOUT) para el cliente. – Dan

+0

El proceso principal podría enviar su respuesta antes de bifurcar; a menos que en realidad estés haciendo más trabajo en el padre después del tenedor. Si los archivos de registro no están en los descriptores STDIN/OUT/ERR, puede simplemente comenzar a cerrar cualquier descriptor abierto> 2 que encuentre en el proceso hijo. – nezroy

+0

Sí, el problema es que el proceso de apache continúa atendiendo a otras solicitudes cuando ha finalizado, matando a su STDERR rompe su registro, y sospecho que matar a su STDIN impide que se comunique con el progenitor padre. De todos modos, lo intenté y no solucionó el problema;) – Dan

0

En mi (anteriormente mod_perl, ahora FCGI) de código, que tengo en la cláusula "si no" del "if ($ kpid)",

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

Además, por razones que se me olvidó, inmediatamente bifurcar nuevamente, y luego en ese niño vuelve a abrir STDIN, STDOUT y STDERR.

por lo que parece:

$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; 
}