2011-07-14 11 views
6

Dlaczego ten fałszywy skrypt utrzymuje wydarzenie, jeśli klient zamknie przeglądarkę (czyli połączenie z serwerem)?Skrypt PHP nie kończy się przy wyjściu przeglądarki

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

Nieoczekiwane dla mnie zgodnie z this. Również wydaje się, że przykład this nie działa.

I set_time_limit z niezerowym parametrem po prostu nic nie robi.

Chciałbym wyjaśnienia.

+0

Ignorujesz przerwanie przez użytkownika, nie robiąc żadnego wyjścia do klienta. – hakre

Odpowiedz

9

Jeśli spróbujesz napisać jakiś wynik do przeglądarki w tej pętli, powinieneś odszukać skrypt, jeśli połączenie zostanie przerwane. Takie zachowanie jest zasugerował w dokumentacji dla ignore_user_abort

Gdy PHP działa jako skrypt z linii poleceń, a tty skrypt idzie się bez skrypt jest zakończony wtedy skrypt umrze następnym razem stara się pisać cokolwiek, chyba że wartość jest ustawiona na PRAWDA

Sam spróbowałem kilku eksperymentów i odkryłem, że nawet jeśli spróbujesz wypróbować jakieś wyjście przeglądarki, skrypt będzie działał, jeśli bufor wyjściowy nie jest jeszcze pełny. Jeśli wyłączysz buforowanie wyjść, skrypt przerwie się, gdy próbujesz wyjść. Ma to sens - warstwa SAPI powinna zauważyć, że żądanie zostało przerwane, gdy próbuje wysłać dane wyjściowe.

Oto przykład ...

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

To pokazuje, co powoduje przerwanie. Gdybyś miał skrypt, który byłby skłonny wejść do niekończącej się pętli bez wyjścia, możesz użyć connection_aborted(), aby sprawdzić, czy połączenie jest nadal otwarte.

+0

Próbowałem tego samego zachowania. – cYrus

+0

@cYrus: Co próbowałeś. Proszę to odzwierciedlić w swoim pytaniu o kod. Musisz wyłączyć ignorowanie anulowania przez użytkownika. Domyślne ustawienie dotyczy IIRC. – hakre

+0

@Paul: Czy możesz podać działający kod? – cYrus

1

ogranicza tylko czas spędzony w kodzie php. Przez większość czasu (domyślam się, że 99,9%) w twoim programie jest spędzany w wywołaniach systemowych, zapisywaniu danych do pliku i spaniu.

ignore_user_abort przerywa tylko wtedy, gdy piszesz coś do klienta (nie w pliku lokalnego) - po prostu nie ma sposób można odróżnić nieużywany oraz zakończonego połączenia poza tym TCP, chyba że klient excplicitely przerywa połączenie z pakietem RST.

+0

To wyjaśnia 'set_time_limit', pisanie czegoś nie powoduje żadnych zmian. – cYrus

+0

Zapisywanie na * wyjście * jest potrzebne, aby wywołać przerwanie wykrywania przez użytkownika IIRC. - http: //www.php.net/manual/pl/features.connection-handling.php – hakre

+0

@hakre Tak, oczywiście losowe pliki lokalne nie mają wpływu na połączenia TCP. Zaktualizowano. – phihag

Powiązane problemy