PHP-скрипт не завершается при выходе из браузера - PullRequest
6 голосов
/ 14 июля 2011

Почему этот фиктивный сценарий продолжает работать, если клиент закрывает браузер (поэтому соединение с сервером)?

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

Это неожиданно для меня согласно этому . Также этот пример не работает.

И set_time_limit с ненулевым параметром просто ничего не делает.

Я хотел бы получить некоторые разъяснения.

Ответы [ 2 ]

9 голосов
/ 14 июля 2011

Если вы попытаетесь записать какой-либо вывод в браузер в этом цикле, сценарий будет прерван, если соединение было разорвано.Это поведение упоминается в документации для ignore_user_abort

При запуске PHP в качестве сценария командной строки, когда tty сценария удаляется без завершения сценария, сценарий умираетв следующий раз он попытается что-то записать, если только значение не установлено в TRUE

. Я сам попробовал несколько экспериментов и обнаружил, что даже если вы попытаетесь что-то сделать из браузера, скрипт продолжит работать, есливыходной буфер еще не заполнен.Если вы отключите буферизацию вывода, сценарий будет прерван при попытке вывода.Это имеет смысл - уровень SAPI должен заметить, что запрос был прерван, когда он пытается передать выходные данные.

Вот пример ...

//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 );
}

Это демонстрирует, что вызывает прерывание.Если у вас был скрипт, который был склонен к бесконечному циклу без вывода, вы можете использовать connection_aborted () , чтобы проверить, открыто ли соединение до сих пор.

1 голос
/ 14 июля 2011

set_time_limit ограничивает только время, проведенное в php-коде.Большую часть времени (я думаю,> 99,9%) в вашей программе тратится на системные вызовы, запись данных в файл и спящий режим.

ignore_user_abort прерывается только тогда, когда вы 'что-то записывает для клиента (не в локальном файле) - просто нет способа отличить неиспользуемое и разорванное соединение в TCP, если только клиент не прерывает соединение с помощью пакета RST.

...