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?
-
Among the difficulties is that a new ajax call would have to be made to the server, which involves a second PHP script running. That second PHP script would need to have access to the thread generated by the first PHP script. I can think of several ways of doing this - but it won't be automatic. You need to make sure to code your PHP in order to make the original thread accessible or controllable in some way by a new and independently created thread. – Wolfman Joe May 13 '13 at 14:17
-
Actually the default behavior of PHP is to abort the process if the client disconnects. – Jon May 16 '13 at 16:39
-
@jon In my situation on windows server it keeps on running after disconnection. However I also don't want PHP to just close the process. I need to ROLLBACK db transactions and safely shutdown it. – asim-ishaq May 16 '13 at 16:43
-
@asim-ishaq: You don't need to rollback transactions because unless you do make it to the end and commit, the database will discard them anyway. If transactions were prone to corruption whenever a database client unexpectedly quit they would be useless. – Jon May 16 '13 at 16:46
-
@jon Furthermore delete some files and log the activity. – asim-ishaq May 16 '13 at 16:48
-
@jon In my case it does not appear to be the default behaviour the import process keeps on running after disconnect. Is there any INI setting for this? we are using win server 2008 and xammp 1.8.1 – asim-ishaq May 16 '13 at 16:53
-
See `ignore_user_abort` as one answer mentions. – Jon May 16 '13 at 16:57
4 Answers
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..\n\n" );
for($i = 1; $i <= 15; $i ++) {
print " ";
file_put_contents ( "con-status.txt", "Running process unit $i \n", 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", "\nUser terminated the process", FILE_APPEND );
die ();
}
}
file_put_contents ( "con-status.txt", "\nAll 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;
}

- 2,190
- 5
- 32
- 55
-
1note that `ob_flush` should be called before `flush`, if output buffering is in use (maybe even ob_end_flush?) http://stackoverflow.com/questions/4191385/php-buffer-ob-flush-vs-flush – metadings Jul 24 '13 at 04:04
Check out PHP connection_aborted()
function. While doing your processing, you can sometimes check for the aborted connection to gracefully cancel the progress, as one would do in an interactive threading model.

- 7,296
- 6
- 30
- 50

- 3,798
- 2
- 28
- 37
-
-
3@metadings This does not seem to work for ajax requests. The ajax request is terminated and the connection_aborted() still return 0. Even I have tried by closing the web-page still the scripts keep on executing. what can be the reason? – asim-ishaq May 13 '13 at 19:15
-
@metadings The function connection_aborted() has a bug and it will aways return 0 see this bug: https://bugs.php.net/bug.php?id=54062 ...Is there any other option? – asim-ishaq May 13 '13 at 19:34
-
Welcome to [PHP - a fractal of bad design](http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/). In the comments on php.net people say you have to `echo` and `flush` something (`[space]` or `\n`) to get it working, so it depends on what you're doing. Beware by echo'ing, you can't change the cookies or send other headers anymore. Also have a look on connection_status! – metadings May 14 '13 at 02:31
-
I have to confirm, the function always returns 0. So I'm sorry. I'm really sorry, PHP5 is the same shit as PHP3, having functions being documented, **and not** doing what expected. Probably there's a magic ini setting, I would not wonder. – metadings May 14 '13 at 02:46
-
https://bugs.php.net/bug.php?id=54062 I see "Status: Not a bug" so not fixed looks like – Darius.V May 26 '23 at 13:04
One way I've found which is the easiest way to handle this time-out issue is as such:
1: set a value on the server as 'processing'. Start an independent thread to do the processing.
2: The initial ajax call returns a success
3: The javascript on the page goes into 'waiting mode' which sends a new ajax request every 10 or 30 or 60 seconds or five or ten minutes or whatever (depending on your situation) to find out whether the value on the server is still set to 'processing'.
4: The independent thread completes. It sets the value on the server to 'done'.
5: The javascript on the page makes its next waiting-mode query, and returns 'done' and the appropriate data.
4b: If an obscene amount of time goes by without a 'done', it registers as a failure. How much time is obscene depends upon your situation. Send an ajax call updating the value from 'processing' to 'cancel'. 5b: The independent thread periodically checks the status to make sure it's still set to 'processing'. If it sees a mode-shift to 'cancel' it cancels itself.

- 799
- 1
- 8
- 23
This is what you're looking for: http://php.net/manual/en/function.ignore-user-abort.php
Stopping a script in the middle of execution can lead to unexpected results, so caveat emptor

- 12,119
- 5
- 32
- 34