2011-07-14 10 views
6

¿Por qué esta secuencia de comandos ficticia sigue ejecutando eventos si el cliente cierra el navegador (por lo que la conexión al servidor)?La secuencia de comandos PHP no sale en el explorador exit

 
while (true) 
{ 
    sleep(1); 
    file_put_contents('/tmp/foo' , "I'm alive ".getmypid()."\n" , FILE_APPEND); 
} 

Es inesperado en mí según this. También el ejemplo this no parece funcionar.

Y set_time_limit con un parámetro distinto de cero simplemente no hace nada.

Me gustaría obtener algunas aclaraciones.

+0

Está ignorando el aborto del usuario mientras no realiza ningún tipo de salida al cliente. – hakre

Respuesta

9

Si intenta escribir alguna salida en el navegador en ese bucle, debe encontrar que la secuencia de comandos se cancela si la conexión ha finalizado. Este comportamiento se insinúa en la documentación de ignore_user_abort

Cuando se usa PHP como un script de línea de comandos, y TTY del script va lejos sin el guión está terminado entonces el script morirá el próxima vez que intenta escribir nada, a menos que el valor se establece en TRUE

he probado unos cuantos experimentos a mí mismo, y se encontró que incluso si lo hace intentar alguna salida navegador, el guión sigue funcionando si el búfer de salida no está completa aún. Si desactiva el búfer de salida, la secuencia de comandos se cancelará cuando se intente la salida. Esto tiene sentido: la capa SAPI debe notar que la solicitud ha terminado cuando intenta transmitir la salida.

He aquí un ejemplo ...

//ensure we're not ignoring aborts.. 
ignore_user_abort(false); 

//find out how big the output buffer is 
$buffersize=max(1, ini_get('output_buffering')); 


while (true) 
{ 
    sleep(1); 

    //ensure we fill the output buffer - if the user has aborted, then the script 
    //will get aborted here 
    echo str_repeat('*', $buffersize)."\n"; 

    file_put_contents('/tmp/foo' , "I'm alive ".getmypid()."\n" , FILE_APPEND); 
} 

Eso demuestra lo que desencadena el aborto. Si tenía un script que era propenso a ingresar un bucle sin fin sin salida, puede usar connection_aborted() para probar si la conexión aún está abierta.

+0

Probé eso, el mismo comportamiento. – cYrus

+0

@cYrus: ¿Qué has intentado? Por favor, refleje eso en su código de preguntas. Debes deshabilitar ignorar el aborto del usuario. La configuración predeterminada es en IIRC. – hakre

+0

@Paul: ¿podría proporcionar el código de trabajo? – cYrus

1

set_time_limit solo restringe el tiempo pasado en el código php. La mayoría de las veces (supongo> 99.9%) en su programa se gasta en llamadas al sistema, escribiendo datos en un archivo y durmiendo.

ignore_user_abort sólo se aborta cuando se está escribiendo algo al cliente (no en un archivo local) - simplemente no hay manera que usted puede distinguir alguna toma de salida y una conexión terminado de otra manera en TCP, a menos que el cliente termina excplicitely la conexión con un paquete RST.

+0

Eso explica 'set_time_limit', escribiendo algo no hace ningún cambio. – cYrus

+0

Se necesita escribir en la * salida * para activar el usuario para cancelar la detección de IIRC. - http: //www.php.net/manual/es/features.connection-handling.php – hakre

+0

@hakre Sí, por supuesto, los archivos locales aleatorios no tienen ningún efecto en las conexiones TCP. Actualizado. – phihag

Cuestiones relacionadas