简体   繁体   中英

Confusing PHP/AJAX timeout after 900 secs(15 mins)

all of the below is based on Linux, recent Apache, recent PHP module for Apache.

I am experiencing an unexpected behavior for my AJAX+PHP based web-application. It is quite a simple AJAX approach, basically involving a request to a PHP-script (execute.php) that runs for some time (few seconds to several minutes). As a test-setup, the PHP-script (execute.php) basically just sleeps for a certain amount of time. When this amount is 899 seconds, it works, but when I set it to 900, the answer of the PHP-script (simple echo() ) seems to expire or something like this (what is exactly the cause or reason is actually unknown to me) as the request is not taking notice of it and thus not responding and the respective innerHTML is not updated, as expected. Please find the code below.

I am now wondering where this "timeout" of 900 seconds comes from and even more important, how can I prevent that from happening? After all, I thought that this was, at least, one general idea of AJAX to handle asynchronous calls and notify the client as soon as a request has changed its state?!

process.php

<?php
session_start();

include("functions.php");
include("env.php");

html_head("Processing...");

$sid = $_SESSION['my_sid'];

?>
<script type="text/javascript">
function run_analyses(params){
    <?php
    print "var sid = \"". $sid ."\";
    ";
    ?>

    // Use AJAX to execute the programs independenantly in the background
    // Allows for the user to close the process-page and come back at a later point to the results-link, w/o need to wait.
    if (window.XMLHttpRequest)
    {
        http_request = new XMLHttpRequest();
    }
    else
    {
        //Fallback for IE5 and IE6, as these don't support the above writing/code
        http_request = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //Is http_request still false
    if (!http_request)
    {
        alert('Ende :( Kann keine XMLHTTP-Instanz erzeugen');
    }

    http_request.onreadystatechange=function(){
        if (http_request.readyState==4 && http_request.status==200){
            // Maybe used to display the progress of the execution
            document.getElementById("output").innerHTML=http_request.responseText;
        }
    };

    http_request.open("POST","execute.php",true);
    //Send the proper header information along with the request
    http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    http_request.setRequestHeader("Content-length", params.length);
    http_request.setRequestHeader("Connection", "close");
    http_request.send(params);
};
</script>

<?php
$params "some_params";
print "
Starting AJAX-call<br>
<div style=\"width:400px; border: 1px black solid;\" id=\"output\">Use this to display an information about the progress</div>
<script type=\"text/javascript\">
    run_analyses('".$params."');
</script>
<form action=\"./usersets/". $sid ."/results.html\" id=\"go_to_results\" method=\"POST\">
<input type='hidden' name=\"session_id\" value=\"" .$sid. "\">
</form>
";
html_foot();
?>

and execute.php:

<?php

session_start();

include("functions.php");
include("env.php");

$sid = $_SESSION['my_sid'];

// Used to get the time at start of processing
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;
session_write_close();

sleep(900);  //899 here works

session_start();
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$finish = $time;
$total_time = round(($finish - $start), 3);
//echo 'Page generated in '.$total_time.' seconds.'."\n";

// Make it accessible for the results
$_SESSION['process_time'] = $total_time;

echo("none");

?>

So the text after "Starting AJAX call" is updated to "none" when the PHP-script sleeps for 899 seconds, but stays "Use this to display an information about the progress" if that value is 900 seconds.

I am really looking forward to your suggestions.

Best,

Shadow

EDIT

Doing grep max_execution $(locate php.ini ) gives:

/etc/php5/apache2/php.ini:max_execution_time = 30
/usr/share/doc/php5-common/examples/php.ini-development:max_execution_time = 30
/usr/share/doc/php5-common/examples/php.ini-production:max_execution_time = 30
/usr/share/php5/php.ini-production:max_execution_time = 30
/usr/share/php5/php.ini-production-dist:max_execution_time = 30
/usr/share/php5/php.ini-production.cli:max_execution_time = 30

EDIT2 When calling the scripts locally (apache webserver running on my local linux machine) in my browser interestingly it behaves as expected and respectes the return of the request. But it exhibits the above unexpected behavior when run on a webserver running on a different machine. Any clues on that? Because I don't have any... Sorry.

In your php.ini there is a max_execution_time , the default is 30 seconds, so it seems somewhere it has been set to 900. So I would check there first. Info: http://www.php.net/manual/en/info.configuration.php#ini.max-execution-time

As for solving it, you can edit the php.ini to set that value really high (or 0 for unlimited), or alternatively you might be able to use this function: http://php.net/manual/en/function.set-time-limit.php to reset it after say 300 seconds.

Hope this helps!

Edit: added Lee's suggestion of 0 value max_execution_time

Edit 2:

Just found something interesting here http://www.php.net/manual/en/function.set-time-limit.php#75557

Please note that, under Linux, sleeping time is ignored, but under Windows, it counts as execution time.

So, that could be why its allowed to execute for longer than 30 seconds, but still cutting it off eventually.

Search for the value 900 in all your php.ini and .htaccess :

grep -HR 900 $(locate php.ini ) $(locate -e .htaccess )

also search for 900 and fractions of 900 in your source code:

cd /var/www/ #path_to_yoursite
grep --color=auto -HR "=\s*900\b"
grep --color=auto -HR "=\s*20\s*\*\s*45\b"
grep --color=auto -HR "=\s*15\s*\*\s*60\b"
...

I tried your example and place it in a different host (not localhost). In my case it ran fine and got the "none" value after 900 seconds. I removed the SESSION calls to simplify the example...

Try it without session. If that changes something, then maybe "session.cookie_lifetime" value could be related.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM