9

Suppose I make an AJAX HTTP Request from jQuery to a backend PHP script. The request is made, the PHP script starts running and doing its magic. Suppose I then change to another website, away from the site where the original AJAX Request was made. As well, I do this before the PHP script finishes and has time to do a HTTP Response back. Does the PHP script finish running and doing its thing even though I've switched to another website before I got the HTTP Response?

So the order is this.

  • I'm on website www.xyz.com
  • I have a jQuery handler that kicks off an AJAX request to blah.php
  • blah.php starts running
  • I go to website www.abc.com soon after without waiting for a response from blah.php

What's going on with blah.php? Is execution still going on? Did it stop? I mean it didn't get a chance to respond so...

Steve Nguyen
  • 5,854
  • 5
  • 21
  • 39
  • 5
    Why don't you try it yourself? Write a php script that sleeps for ten seconds before sending a response, make it log everything it does, call it from ajax, then navigate away, wait ten seconds and inspect the log. – tdammers Jul 21 '11 at 19:57
  • 1
    When you make an Ajax-request, all the communication that happens between the browser and the server is (1) the HTTP-request that the browser sends to the server, and (2) the HTTP-response that the server sends back to the browser. So yes, the server will process the request fully and send the HTTP-response regardless of whether or not you stay on that page. – Šime Vidas Jul 21 '11 at 19:58
  • I think you should review (and try) genesis's solution. The documentation for the ignore_user_abort function might be misleading because it describes its behaviour when used from the CLI, but the function is primarily used to get or set whether or not a script continues running when called over the web and the user aborts (stops/navigates away). It works with the exception of a few odd web server SAPIs and configurations. You can use the other solutions to experimentally verify it. – Jonathan Amend Aug 29 '11 at 21:29

4 Answers4

8

This may depend on your server configuration, but in general the script will continue to execute despite a closed HTTP connection.

I have tested this with Apache 2 + PHP 5 as mod_php. I would expect similar behaviour with PHP as CGI and with other webservers but do not know for certain.

The best way to determine for certain on your configuration is, as @tdammers suggests: set up a test script something like the following and monitor the log.

<?php
error_log('Test script started.');
for ($i = 1; $i < 13; $i++) {
    sleep(10);
    error_log('Test script got to ' . (10 * $i) . ' seconds.');
}
error_log('Test script got to the end.');
?>

Access this script (at /test.php or whatever) then before you get any results, hit stop on your browser. This is equivalent to navigating away before your XHR returns. You could even have it as the target of an XHR and navigate away.

Then check your error log: you should have a start and then messages every 10 seconds for two minutes and an end. You can modify how high $i gets to ensure your script will reach its anticipated maximum execution time if you'd like to test that too.

You don't have to use error_log() - you could write to a file, or make some other persistent change on the server that can be checked without needing to keep the client connection open.

The script execution time may stop before then because of the max_execution_time php.ini directive - but in any case this should be distinct from when the webserver times out.

Community
  • 1
  • 1
mjec
  • 1,817
  • 12
  • 20
  • 1
    Just to clarify: [from the php manual](http://php.net/manual/en/function.set-time-limit.php) The max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real. – Fabio Aug 30 '11 at 11:52
6

Try ignore_user_abort(true);

ignore_user_abort(true);

it should not abort proccessing of your code

genesis
  • 50,477
  • 20
  • 96
  • 125
  • To quote from that page (emphasis mine), "When running PHP **as a command line script**, and the script's **tty** goes away without the script being terminated then the script will die the next time it tries to write anything, unless value is set to TRUE" -- this is for *terminals* not *web servers* by my read. – Stephen P Jul 21 '11 at 20:06
  • @StephenP He's 15 years old, cut him some slack. :-p I'm impressed he's not saying something rude or obscene. – Steve Nguyen Jul 21 '11 at 20:11
  • 3
    @FinalForm: What does this answer has to do with my age? – genesis Jul 21 '11 at 20:12
  • @genesis the fact that you actually misread my question and gave an answer that didn't even answer my question. :-) – Steve Nguyen Jul 21 '11 at 20:13
  • @FinalForm: I'm not sure if executing still goes, but I'm sure it still goes if you add this function to your script... – genesis Jul 21 '11 at 20:16
  • @genesis what stephenp was trying to say to you was that command, ignore_user_abort only works in the linux/unix command line shell and not through a browser. – Steve Nguyen Jul 21 '11 at 20:17
  • @FinalForm: I did not say it will respond you after execution is done, I told that you can let php to continue when you do include this include into your script. Or am I still misreading? – genesis Jul 21 '11 at 20:19
  • @FinalForm: and what page Stephen P talks about? – genesis Jul 21 '11 at 20:25
  • @FinalForm - I didn't check his ID before commenting, and I *did* cut him some slack by not downvoting, and I don't think I was particularly harsh in any case, I was just emphasizing something in the doc that seemed an important distinction. – Stephen P Jul 21 '11 at 20:34
  • @genesis - I quoted from the page you linked to, the php doc for ignore_user_abort. – Stephen P Jul 21 '11 at 20:35
0

You might want to check out the answers to This Question. Basically when you make your ajax call to a php function which calls the exec() function as shown in the answers to that question, you'll get an ajax response almost immediately, since your php function doesn't actually need to process anything. This way, it shouldn't matter if the user leaves the page. Here's a small example:

ajax call in html file: $.ajax({url: 'blah.php'});

blah.php file: exec('bash -c "exec nohup setsid php really_slow_script.php > /dev/null 2>&1 &"');

And then finally in really_slow_script.php, just include the actual code you want to run.

I successfully used this kind of logic to allow users to post an already uploaded video from their account on my website to youtube. (The video had to be sent to youtube, and since videos are generally large files, I didn't want the user to have to wait while the video was being uploaded to youtube)

Community
  • 1
  • 1
Brian Glaz
  • 15,468
  • 4
  • 37
  • 55
0

Navigating away will trigger a disconnect message on the server. The implications of that entirely depends on what what your server has been configured to do.

By default, the server will be set up so that a disconnect will not interrupt the way that the program functions. It is possible, however, to make it so that a user disconnect will trigger the function which has been registered with register_shutdown_function, garbage collection will occur, and the script will terminate.

Because it is something which can be configured several different places, it might be easiest to just run a test, but this is a php.ini directive. If you want to configure this on a global level, you can set ignore_user_abort = Off in php.ini. If you want this on a site-specific level, you can use php_value ignore_user_abort off in the htaccess in the parent directory of the current site. Otherwise you can use ignore_user_abort(false);.

Of course, there is no guarantee on a shared server that you have control of htaccess or php.ini, so you might just need to use ignore_user_abort(false);.

cwallenpoole
  • 79,954
  • 26
  • 128
  • 166