Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
650 views
in Technique[技术] by (71.8m points)

ajax - PHP auto-kill a script if the HTTP request is cancelled/closed

The problem is that for a long process the PHP script keeps on executing whether or not the client browser is currently connected or not. Is there any possibility that if the client has terminated the Ajax call to a script then the script also terminates on server?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As pointed out by @metadings php does have a function to check for connection abort named connection_aborted(). It will return 1 if connection is terminated otherwise 0.

In a long server side process the user may need to know if the client is disconnected from the server or he has closed the browser then the server can safely shutdown the process.

Especially in a case where the application uses php sessions then if we left the long process running even after the client is disconnected then the server will get unresponsive for this session. And any other request from the same client will wait until the earlier process executes completely. The reason for this situation is that the session file is locked when the process is running. You can however intentioanlly call session_write_close() method to unlock it. But this is not feasible in all scenarios, may be one need to write something to session at the end of the process.

Now if we only call connection_aborted() in a loop then it will always return 0 whether the connection is closed or not.

0 means that the connection is not aborted. It is misleading. However, after re-search and experiments if have discovered that the output buffer in php is the reason.

First of all in order to check for aborts the developer in a loop must send some output to the client by echoing some text. For example:

print " ";

As the process is still running, the output will not be sent to the client. Now to send output we then need to flush the output buffer.

flush ();
ob_flush ();

And then if we check for aborts then it will give correct results.

if (connection_aborted () != 0) {
  die();
}

Following is the working example, this will work even if you are using PHP session:

session_start ();
ignore_user_abort ( TRUE );

file_put_contents ( "con-status.txt", "Process started..

" );

for($i = 1; $i <= 15; $i ++) {

    print " ";

    file_put_contents ( "con-status.txt", "Running process unit $i 
", FILE_APPEND );
    sleep ( 1 );

    // Send output to client
    flush ();
    ob_flush ();

    // Check for connection abort
    if (connection_aborted () != 0) {
        file_put_contents ( "con-status.txt", "
User terminated the process", FILE_APPEND );
        die ();
    }

}

file_put_contents ( "con-status.txt", "
All units completed.",  FILE_APPEND );

EDIT 07-APR-2017

If someone is using Fast-Cgi on Windows then he can actually terminate the CGI thread from memory when the connection is aborted using following code:

if (connection_aborted () != 0) { apache_child_terminate(); exit; }


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...