I've got this PHP script i am starting in my web browser. It reads a lot of data and writes it to a database.
What is happening
when i click BACK in the browser (or go to another link/page)?
close the web browser?
Will the the script run in the background until it's finished?
It should continue running until finished unless the php.ini setting ignore_user_abort is set (disabled by default). Since ignore_user_abort is disabled by default, the default PHP behavior is to terminate the script prior to completion if it detects the user has gone away. To change this, call ignore_user_abort(true); at the beginning of your script.
That said, in somewhat short lived scripts, PHP may not detect the user has gone away until the processing finishes even if the user disconnected several seconds earlier.
See ignore_user_abort() which has an example script that shows it will continue running after the user disconnects.
Also note, PHP will not detect that the user has aborted the connection until an attempt is made to send information to the client. Simply using an echo statement does not guarantee that information is sent, see flush().
If you had started a session, the session file may not be closed (unlocked) until the script finishes running so future page loads by the same user that attempt to start a session may hang until the script with the session lock finishes. To avoid this, you can call session_write_close when session information is no longer needed if you plan on running a script for an extended period of time.
This reference on connection handling in php should also be of interest to you.
Related
Say a user clicked a button, which resulted in a jquery ajax request being sent to my server.
The server begins a complicated process in response to the ajax request. Lets say that process takes 5 minutes to finish.
In the meantime the user gets bored and closes his browser window.
Will the script on the server continue its processing until it finishes on its normal time, or will it stop?
Same thing if the user visits a url, e.g example.com/process.php?data=xxx. This starts process.php which begins to process the data, and will take 5 mins to finish processing.
Will this processing always continue on, or if the user closes the browser, will it stop?
(I'm asking because I'm concerned about the process being left half finished and resulting in corrupt data).
PHP won't notice that the browser closed the connection unless it tries to output something (e.g. echo). If it fails to output something, the script will be terminated unless ignore_user_abort is On.
So the script will terminate only if the following conditions are met:
the script attempts to output something (because the script won't notice that the user aborted the connection until then)
AND php's ignore_user_abort setting is off (if the setting is off, php will terminate the script if fails to output something)
You can avoid the script from terminating by enabling ignore_user_abort.
You can use connection_aborted() at anytime to check is the browser aborted the request.
A script can terminate unexpectedly for other reasons (e.g. max execution time, exception, etc); so you should make use of transactions, so that half-finished changes are canceled if the script terminates abnormally.
See: http://php.net/manual/en/function.ignore-user-abort.php. It depends on the ignore_user_abort setting and a few other conditions.
The default behaviour for PHP is that your script will be aborted when the remote client disconnects, usually caused by a user closing their browser or hitting the stop button. It can also happen when someone closes a remote connection to a script run in CLI mode. The one exception to your script aborting is if you have registered a shutdown function using register_shutdown_function(). For a thorough explanation please see the Connection Handling page in PHP docs.
The point at which the script actually terminates is dependent upon when flush() is called, which essentially attempts to push current output all the way to the browser/client. At this point if the state of the connection is ABORTED then the script will terminate, unless we are ignoring user abort.
The important thing to note is that you can control whether this behaviour occurs or not, as you specify sometimes it is undesirable for this to happen. Using the ignore_user_abort() function or setting the associated directive in php.ini.
Unless it's launched as a background process i.e. with the & at the end... it will just terminate.
Closing browser a bit more to it... It will stop eventually, but will process for a little while before web server realises connection is gone.
Say a user clicked a button, which resulted in a jquery ajax request being sent to my server.
The server begins a complicated process in response to the ajax request. Lets say that process takes 5 minutes to finish.
In the meantime the user gets bored and closes his browser window.
Will the script on the server continue its processing until it finishes on its normal time, or will it stop?
Same thing if the user visits a url, e.g example.com/process.php?data=xxx. This starts process.php which begins to process the data, and will take 5 mins to finish processing.
Will this processing always continue on, or if the user closes the browser, will it stop?
(I'm asking because I'm concerned about the process being left half finished and resulting in corrupt data).
PHP won't notice that the browser closed the connection unless it tries to output something (e.g. echo). If it fails to output something, the script will be terminated unless ignore_user_abort is On.
So the script will terminate only if the following conditions are met:
the script attempts to output something (because the script won't notice that the user aborted the connection until then)
AND php's ignore_user_abort setting is off (if the setting is off, php will terminate the script if fails to output something)
You can avoid the script from terminating by enabling ignore_user_abort.
You can use connection_aborted() at anytime to check is the browser aborted the request.
A script can terminate unexpectedly for other reasons (e.g. max execution time, exception, etc); so you should make use of transactions, so that half-finished changes are canceled if the script terminates abnormally.
See: http://php.net/manual/en/function.ignore-user-abort.php. It depends on the ignore_user_abort setting and a few other conditions.
The default behaviour for PHP is that your script will be aborted when the remote client disconnects, usually caused by a user closing their browser or hitting the stop button. It can also happen when someone closes a remote connection to a script run in CLI mode. The one exception to your script aborting is if you have registered a shutdown function using register_shutdown_function(). For a thorough explanation please see the Connection Handling page in PHP docs.
The point at which the script actually terminates is dependent upon when flush() is called, which essentially attempts to push current output all the way to the browser/client. At this point if the state of the connection is ABORTED then the script will terminate, unless we are ignoring user abort.
The important thing to note is that you can control whether this behaviour occurs or not, as you specify sometimes it is undesirable for this to happen. Using the ignore_user_abort() function or setting the associated directive in php.ini.
Unless it's launched as a background process i.e. with the & at the end... it will just terminate.
Closing browser a bit more to it... It will stop eventually, but will process for a little while before web server realises connection is gone.
If I have a PHP page that is doing a task that takes a long time, and I try to load another page from the same site at the same time, that page won't load until the first page has timed out. For instance if my timeout was set to 60 seconds, then I wouldn't be able to load any other page until 60 seconds after the page that was taking a long time to load/timeout. As far as I know this is expected behaviour.
What I am trying to figure out is whether an erroneous/long loading PHP script that creates the above situation would also affect other people on the same network. I personally thought it was a browser issues (i.e. if I loaded http://somesite.com/myscript.php in chrome and it start working it's magic in the background, I couldn't then load http://somesite.com/myscript2.php until that had timed out, but I could load that page in Firefox). However, I've heard contradictory statements, saying that the timeout would happen to everyone on the same network (IP address?).
My script works on some data imported from sage and takes quite a long time to run - sometiems it can timeout before it finishes (i.e. if the sage import crashes over the weeked), so I run it again and it picks up where it left off. I am worried that other staff in the office will not be able to access the site while this is running.
The problem you have here is actually related to the fact that (I'm guessing) you are using sessions. This may be a bit of a stretch, but it would account for exactly what you describe.
This is not in fact "expected behaviour" unless your web server is set up to run a single process with a single thread, which I highly doubt. This would create a situation where the web server is only able to handle a single request at any one time, and this would affect everybody on the network. This is exactly why your web server probably won't be set up like this - in fact I suspect you will find it is impossible to configure your server like this, as it would make the server somewhat useless. And before some smart alec chimes in with "what about Node.js?" - that is a special case, as I am sure you are already well aware.
When a PHP script has a session open, it has an exclusive lock on the file in which the session data is stored. This means that any subsequent request will block at the call to session_start() while PHP tries to acquire that exclusive lock on the session data file - which it can't, because your previous request still has one. As soon as your previous request finishes, it releases it's lock on the file and the next request is able to complete. Since sessions are per-machine (in fact per-browsing session, as the name suggests, which is why it works in a different browser) this will not affect other users of your network, but leaving your site set up so that this is an issue even just for you is bad practice and easily avoidable.
The solution to this is to call session_write_close() as soon as you have finished with the session data in a given script. This causes the script to close the session file and release it's lock. You should try and either finish with the session data before you start the long running process, or not call session_start() until after it has completed.
In theory you can call session_write_close() and then call session_start() again later in the script, but I have found that PHP sometimes exhibits buggy behaviour in this respect (I think this is cookie related, but don't quote me on that). Obviously, pay attention to the fact the setting cookies modifies the headers, so you have to call session_start() before you output any data or enable output buffering.
For example, consider this script:
<?php
session_start();
if (!isset($_SESSION['someval'])) {
$_SESSION['someval'] = 1;
} else {
$_SESSION['someval']++;
}
echo "someval is {$_SESSION['someval']}";
sleep(10);
With the above script, you will have to wait 10 seconds before you are able to make a second request. However, if you add a call to session_write_close() after the echo line, you will be able to make another request before the previous request has completed.
Hmm... I did not check but I think that each request to the webserver is handled in a thread of its own. Thereby a different request should not be blocked. Just try :-) Use a different browser and access your page while the big script is running!
Err.. I just see that this worked for you :-) And it should for others, too.
When a long-running PHP file is executing, and the user cancels the page request in their browser midway, is the rest of the script ran on the server?
PHP normally terminates script execution once it realizes that the connection is closed:
PHP will not detect that the user has aborted the connection until an
attempt is made to send information to the client. Simply using an
echo statement does not guarantee that information is sent, see
flush().
You can keep your script running using ignore_user_abort().
Also, there is a default time limit for which scripts are allowed to run. You may want to override that using set_time_limit().
I tested this once on a long running process and discovered that the script will continue to run once it has not exceeded the maximum time to execute.
For me (using XAMPP on an older computer), cancelling the web page in the middle of an operation meant to process one million primary records, with a couple of other tables being updated in the process, the MySQL database operations kept going, which tells me that the PHP script kept running on the server. By "cancelling," I mean clicking the stop button on the tab, but not closing the tab altogether. BTW: I had established set_time_limit() to 0 to keep the script from timing out before completing in absence of cancelling.
I want to run a relatively time consuming script based on some form input, but I'd rather not resort to cron, so I'm wondering if a php page requested through ajax will continue to execute until completion or if it will halt if the user leaves the page.
It doesn't actually output to the browser until a json_encode at the end of the file, so would everything before that still execute?
It depends.
From http://us3.php.net/manual/en/features.connection-handling.php:
When a PHP script is running normally
the NORMAL state, is active. If the
remote client disconnects the ABORTED
state flag is turned on. A remote
client disconnect is usually caused by
the user hitting his STOP button.
You can decide whether or not you want
a client disconnect to cause your
script to be aborted. Sometimes it is
handy to always have your scripts run
to completion even if there is no
remote browser receiving the output.
The default behaviour is however for
your script to be aborted when the
remote client disconnects. This
behaviour can be set via the
ignore_user_abort php.ini directive as
well as through the corresponding
php_value ignore_user_abort Apache
httpd.conf directive or with the
ignore_user_abort() function.
That would seem to say the answer to your question is "Yes, the script will terminate if the user leaves the page".
However realize that depending on the backend SAPI being used (eg, mod_php), php cannot detect that the client has aborted the connection until an attempt is made to send information to the client. If your long running script does not issue a flush() the script may keep on running even though the user has closed the connection.
Complicating things is even if you do issue periodic calls to flush(), having output buffering on will cause those calls to trap and won't send them down to the client until the script completes anyway!
Further complicating things is if you have installed Apache handlers that buffer the response (for example mod_gzip) then once again php will not detect that the connection is closed and the script will keep on trucking.
Phew.
It depends on your settings - usually it will stop but you can use ignore_user_abort() to make it carry on.
Depending on the configuration of the web server and/or PHP, the PHP process may, or may not, kill the thread when the user terminates the HTTP connection. If an AJAX request is pending when the user walks away from the page, it is dependent on the browser killing the request (not guaranteed) ontop of your server config (not guaranteed). Not the answer you want to hear!
I would recommend creating a work queue in a flat file or database that a constantly-running PHP daemon can poll for jobs. It doesn't suffer from cron delay but keeps CPU/memory usage to a usable level. Once the job is complete, place the results in the flat file/database for AJAX fetch. Or promise to e-mail the user once the job is finished (my preferred method).
Hope that helps
If the client/user/downloader/viewer aborts or disconnects, the script will keep running until something tries do flush new data do the client. Unless you have used
ignore_user_abort(), the script will die there.
In the same order, PHP is unable to determine if client is still there without trying to flush any data to the httpd.
found the actual solution for my case of it not terminating the connection. The SESSION on my Apache/Php server needed to close before the next one could start.
Browser waits for ajax call to complete after abort.