oliver nadj
oliver nadj

Reputation: 858

set_time_limit, max_execution_time does not cause fatal error on expitation

recently i working on a health check script run as php-fpm/nginx and i want to make this script trigger error after a shorter execution time than a regular php script on the same server. something must be wrong if health check took a lot of time for execution.

but i did not figured out why that script ignore execution time limits. eg:

//healthcheck.php
error_reporting(E_ALL);
error_reporting(1);
echo "initial max_execution_time: " . ini_get('max_execution_time') . "\n";
print_r(set_time_limit(2));
echo " - set_time_limit\n";
print_r(ini_set('max_execution_time', 2));
echo " - max_execution_time\n";
echo "altered max_execution_time: " . ini_get('max_execution_time') . "\n";
sleep(4);
print_r(getrusage());
echo 'Current PHP version: ' . phpversion() . "\n";
die('it should not happen');

returns this:

initial max_execution_time: 30
1 - set_time_limit
2 - max_execution_time
altered max_execution_time: 2
Array
(
    [ru_oublock] => 0
    [ru_inblock] => 0
    [ru_msgsnd] => 0
    [ru_msgrcv] => 0
    [ru_maxrss] => 15032
    [ru_ixrss] => 0
    [ru_idrss] => 0
    [ru_minflt] => 1681
    [ru_majflt] => 0
    [ru_nsignals] => 0
    [ru_nvcsw] => 26
    [ru_nivcsw] => 9
    [ru_nswap] => 0
    [ru_utime.tv_usec] => 5999
    [ru_utime.tv_sec] => 0
    [ru_stime.tv_usec] => 6998
    [ru_stime.tv_sec] => 0
)
Current PHP version: 5.4.35
it should not happen

Upvotes: 2

Views: 1568

Answers (3)

Theo SCHAEFFER
Theo SCHAEFFER

Reputation: 46

Here is another alternative:

2) Using declare(), see http://php.net/manual/en/control-structures.declare.php

For example:

define("MAX_EXECUTION_TIME", 10); # seconds

$timeline = time() + MAX_EXECUTION_TIME;

function check_timeout()
{
if( time() < $GLOBALS['timeline'] )
return;

# timeout reached:
echo "<html><html>Sorry, we are very busy, retry later!</body>        </html>";
exit;
}

register_tick_function("check_timeout");

declare( ticks=1 ){
# here the process that might require
# so much time; any output generated is
# keep inside a string $s
}

# Ok, process completed, output the result:
echo $s;

From: http://bytes.com/topic/php/answers/620062-how-handle-php-execution-timeouts-gracefully

I don't recommend the usage of $GLOBALS though, I'd pass timeline as an arg of register_tick_function(). http://php.net/manual/en/function.register-tick-function.php

Upvotes: 2

HectorJ
HectorJ

Reputation: 6324

From the PHP documentation:

The maximum execution time is not affected by system calls, stream operations etc.

I'm guessing sleep uses a system call.

Replacing the sleep call by some dummy long-running calculation makes the script fail as expected:

<?php
//healthcheck.php
error_reporting(E_ALL);
error_reporting(1);
echo "initial max_execution_time: " . ini_get('max_execution_time') . "\n";
print_r(set_time_limit(2));
echo " - set_time_limit\n";
print_r(ini_set('max_execution_time', 2));
echo " - max_execution_time\n";
echo "altered max_execution_time: " . ini_get('max_execution_time') . "\n";

$dummy = 2;
for($i=0;$i<1000000000;$i++){
    $dummy *= 2;
}

print_r(getrusage());
echo 'Current PHP version: ' . phpversion() . "\n";
die('it should not happen');

Output:

PHP Fatal error: Maximum execution time of 2 seconds exceeded in /home/hjusforgues/maxExecutionTime.php on line 14

Upvotes: 2

Luis &#193;vila
Luis &#193;vila

Reputation: 699

The duration of sleep is ignored by PHP's max execution time.

<?php

set_time_limit(20);

while ($i<=10)
{
        echo "i=$i ";
        sleep(100);
        $i++;
}

?>

Output:
i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10

Upvotes: 0

Related Questions