Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set_time_limit is not affecting PHP-CLI

Tags:

php

How to solve set_time_limit not affecting PHP-CLI?

#!/usr/bin/php -q 
<?php
set_time_limit(2);
sleep(5); // actually, exec() call that takes > 2 seconds
echo "it didn't work again";
like image 226
Devrim Avatar asked Apr 14 '10 04:04

Devrim


People also ask

What is set_time_limit in PHP?

The set_time_limit() function lets you set how long a script should be allowed to execute. This value is usually set inside php. ini under the max_execution_time setting; however, you can override that here. The function takes one parameter, which is the number of seconds you want the script to have.

Can we set infinite execution time in PHP?

Yes, it is possible to set an infinite execution time for the PHP Script. We can do it by adding the set_time_limit() function at the beginning of the PHP script. The set_time_limit() function takes only one parameter that is int value which is in seconds and it returns a boolean value.

What is the default execution time set in set_time_limit () in PHP?

The default limit is 30 seconds or, if it exists, the max_execution_time value defined in the php. ini . When called, set_time_limit() restarts the timeout counter from zero.


2 Answers

The max_execution_time limit, which is what set_time_limit sets, counts (at least, on Linux) the time that is spent by the PHP process, while working.

Quoting the manual's page of set_time_limit() :

Note: The set_time_limit() function and the configuration directive 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.

When, you are using sleep(), your PHP script is not working : it's just waiting... So the 5 seconds you are waiting are not being taken into account by the max_execution_time limit.

like image 173
Pascal MARTIN Avatar answered Oct 01 '22 05:10

Pascal MARTIN


The solution here is to use pcntl_fork(). I'm afraid it's POSIX only. PHP will need to be compiled with --enable-pcntl and not --disable-posix. Your code should look something like this:

<?php

function done($signo)
{
    // You can do any on-success clean-up here.
    die('Success!');
}

$pid = pcntl_fork();
if (-1 == $pid) {
    die('Failed! Unable to fork.');
} elseif ($pid > 0) {
    pcntl_signal(SIGALRM, 'done');
    sleep($timeout);
    posix_kill($pid, SIGKILL);
    // You can do any on-failure clean-up here.
    die('Failed! Process timed out and was killed.');
} else {
    // You can perform whatever time-limited operation you want here.
    exec($cmd);
    posix_kill(posix_getppid(), SIGALRM);
}

?>

Basically what this does is fork a new process which runs the else { ... } block. At the (successful) conclusion of that we send an alarm back to the parent process, which is running the elseif ($pid > 0) { ... } block. That block has a registered signal handler for the alarm signal (the done() callback) which terminates successfully. Until that is received, the parent process sleeps. When the timeout sleep() is complete, it sends a SIGKILL to the (presumably hung) child process.

like image 40
mjec Avatar answered Oct 01 '22 07:10

mjec