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.
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.
I am writing a website with php and there is a part of code need huge amount of time to execute.
Since I don't use thread, when I run that code, the whole server is blocked by it. But it's OK.
Hovever, even though I closed that web page, it still executes and blocked my server. I cannot access any page of my website until the process completed.
Since the execution time is very long, so that I set a very long set_time_limit() for it but I don't set ignore_user_abort so that I supposes that it should not run after user abort. Or is it the problem of curl(the code does many curl job)?
Can someone tell me that why the php script cannot stop when the user close the connection? Or there are some way to assure the script can be stopped when user abort?
Thanks.
Closing the browser doesn't tell the server to stop doing something. It doesn't tell the server anything.
Long-running processes don't belong in web applications. Generally you would want some background task to handle the process. Either the web application would spawn this task (this seems like a workable approach) or would in some way queue the processing of this task where a background worker would see that queue (such as a database table polled every X minutes by a daemon process).
The goal is to not block the UI while the task is running. Even if the user were to leave the browser open, the browser itself may "give up" after a while or something else could sever the user from the UX while waiting for too long. Let the user invoke the process, but separate the invocation of the process from the execution of the process so the user can return to the application interface.
From the PHP Manual:
PHP will not detect that the user has aborted the connection until an
attempt is made to send information to the client.
Thus, even using ignore user abort, you must try to interact with the client again inside the script to ensure it aborts correctly. Note that on the page in question there are some additional notes about what constitutes 'sending information' (for example, an Echo doesn't qualify by itself, apparently).
Further Reading:
http://php.net/manual/en/function.ignore-user-abort.php
I recently executed a mysql query via chrome and closed it out. How exactly does a browser stop a PHP script using the stop button? I thought PHP was a server-side language and could not be controlled through a client.
*UPDATE*I'm now aware of SHOW PROCESSLIST, but this only shows you which threads are running.Is there a SQL command I can use to view a executed query with great detail?
A client (Chrome) has nothing to do with the execution of scripts (PHP) on the server, which in turn have no control over database processes (MySQL query).
Look at your servers process list to see what's going on in general (Apache processes).
Or even better: use SHOW PROCESSLIST; on the MySQL console to find the long running query. You may quit it by using KILL ###ID_OF_QUERY###;.
No, you don't need to keep it open. If you exit a running car, does the car turn off? No.
Sorry, that came off a little snotty, but it wasn't intended too.
The browser, in your case Chrome, is not actually running the actual code. The server is. Thus, once the instruction is executed, closing the browser no longer matters as the request has been given to the server.
two functions are essential for executing time consuming php scripts.
it has nothing to do with the browser (as other users already pointed out)
lookup ignore_user_abort and set_time_limit
The script will continue to execute regardless of browser closure. You can free up your browser by sending the response and allowing the php process to continue on.
ignore_user_abort(true);
$response = "Processing!";
header("Connection: close");
header("Content-Length: " . mb_strlen($response));
echo $response;
flush();
// Insert your lengthy query here
The Answer is it depends, as others mentioned you can check what is running on the mysql server by using the show processlist;
If it is a single query that takes a long time, the it will most likely carry on running after the browser has closed. PHP will have sent the request to the Database and will in effect be sat waiting for it to complete, in turn the browser will be waiting for the webserver to finish building the page/resource that is on that url
so the request is: browser <-> web server (<-> php ) <-> mysql in an ideal world if the user cancels the request everything would tidy itself up nicely, but that in my experience sadly is not the case, if one of the chain decides not to wait, the process that it is waiting for doesn't necessarily know until it tries to send the response back and fails
Come on guys, this is PHP 101. Quoted from the manual:
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.
Execution will stop at the next tickable event after the connection flag is set to ABORTED - which will be detected when PHP attempts to flush output to the client
The current MySQL query will finish executing (as the next event that PHP has control over doesn't occur until after the query has completed), but your script would not make it past that, unless you explicitly set ignore_user_abort. It's always important to account for this when writing code.
There are two ways around this
Set ignore_user_abort to true for the invocation of your script
Do not print anything back to the client until after all of your processing is complete - since a connection closed status won't be detected until output is flushed
I was wondering - as I wrote a snippet of code that could update up to 10,000 rows and might take a few seconds to complete, if when the file is accessed via an ajax request, the post query is send to the php file, then the browser is closed, does the file get fully executed? assume it takes about 25 seconds to complete the request, the user might not wait for 25 seconds, is good enough to "ping" this file and let the user browse along or close its browser window as the mysql queries are taking place?
The request has 3 parts
A browser connected to the web server
PHP script that is executed by the server
A query running in the DB server
When you close the browser, connection with the server is closed. The server may or may not kill the started PHP script (if PHP is running as apache module, it would be killed, unless ignore_user_abort is called). Also the web server may have a time limit for the request and either kill the script or just send the client a connection timeout message, without killing the script, but without giving it the chance to send anything to the browser.
Here is the tricky part - the update is running in the database and it won't be killed by the web server, neither by PHP.
So what you want to achieve is pinging a PHP script, that is executing a query, but the client do not wait the result. You may or may not want the query itself to be asyncronous (the PHP script not to wait the query), but you have to tell the client that the request is fulfilled, by sending content-length of 0 for example, and flushing the output (the http headers actually), and running PHP with ignore_user_abort so it continues the execution.
Use ignore-user-abort to continue running the script even after the client has disconnected
ignore_user_abort(true);
set_time_limit(0);
You can use connection_status to track if the connection has disconnected
if (connection_status()!=0) { //connection disconnected
Here's the answer for your question:
http://www.php.net/manual/en/features.connection-handling.php
Normally no, but your script pass in ABORTED status.
More details in the manual page about Connection handling:
http://www.php.net/manual/en/features.connection-handling.php
Internally in PHP a connection status is maintained. There are 3
possible states:
0 - NORMAL
1 - ABORTED
2 - TIMEOUT
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.
As soon as you close the browser, it disconnects from the server before getting the reply. I do not know exactly how different servers behave in this condition but I assume that most of the server will abort the thread that they are working on to reply the request.
Further, things can be different with different operations - i.e. file i/o or database operation. If it is an atomic database operation, my assumption is, it will complete any how.
I am calling a php script over ajax to do some database maintenance. If the user closes the page, hits back, or clicks a link, will the php script be fully executed? Is there a way to do it?
Maybe if the php script called the exec() method or something similar, which would in turn call a script via the console as such:
$ php /var/www/httpdocs/maintenance.php
?
It's a race condition. PHP will detect at some point (usually upon attempting to do output) that Apache is yelling in its face that the remote user has closed the connection. Whether everything you wanted to do is done at that point depends on how your code's structured.
If you want to ensure that all operations are complete before the script shuts itself down, use ignore_user_abort(TRUE), which keeps PHP running after the connection is severed. It's still subject to the user max_execution_time limits and whatnot, but it will not shut down because you disconnected.
As long as the user agent (browser, etc.) has fully sent the request, the server has all it needs and will complete the request and try to send back a response.
In fact, this sort of "pinging" behavior is often used for "heartbeat"-like processes that keep a service warm or perform periodic maintenance.
Once the web request makes it to your server, it really doesn't matter if the user closes their browser or navigates away. Your server will still respond, but no one will be listening for the response.
Varies on the settings, web server, operating system and so on.
Usually the request will be processed as usual, and the response will just never be read. Occasionally, a write might fail earlier, and the request fails while processing.
Once the ajax call is kicked off, the user is free to do whatever they want. If they close the page they simply won't get the feedback (if any ) from the ajax call that was made.
If the php starts executing then it will continue to execute regardless if the user closes the window or navigates away from the page.
The php script will complete, regardless of browser state. The php is parsed on the server, and that doesn't care about whether the client is still open or not.
If the HTTP request was completed, then yes, the PHP script will be executed fully even if the client's computer is closed.