Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

While cycle with time duration on include

Tags:

php

I need to create a cycle to end when it is longer than 20 seconds. I have tried the following code but it's not working, running forever.

EDIT: For simple code it will stop fine, but using the include_once and include the external files keep running even after the 20 seconds expire

bot.php

$starttime = time();


while (time() - $starttime < 20) {    

 include_once 'onefile.php';
 include 'somefile.php';
 include 'somefile2.php';

}

EDIT 2:

With Josh Trii Johnston's answer the proccess is really stopped if not concluded within X seconds. The problem now is that there is another requisit on my case.. The sample provided above does not run alone. It is also included on another loop file like this:

master.php

<?php
       while (1) {   
            include 'bot.php'; 
            sleep(60);
        }

As you can see it is running on a infinite loop and what I want is not stop the entire loop but only "break" the bot.php loop, keeping the main while(1) loop active. With the provided solution it exits all the loops and the process is terminated.

like image 904
ace Avatar asked Sep 02 '15 15:09

ace


2 Answers

PHP is not magic and cannot stop execution mid-script like that. The while condition is only checked once all processing inside your includes are completed.

You can try calling register_tick_function() and provide a callback that can check the time elapsed and exit if needed.

Now with more example!

<?php
declare(ticks=1);

define('START_TIME', time());

// lambda uses START_TIME constant
register_tick_function(function() {
    if (time() - START_TIME > 20) {
        echo 'Script execution halted. Took more than 20 seconds to execute';
        exit(1);
    }
}, true);

include_once 'onefile.php';
include 'somefile.php';
include 'somefile2.php';
?>

This will halt on the next tick that happens after the 20 second mark, not exactly 20 seconds.

Edit #2 Working code based on your current updates

This code works on a similar principle but instead of halting script execution, it throws a TimeLimitException which is then used to jump to a point of execution using goto. It is hacky, but it accomplishes what you need.

<?php
declare(ticks=1);

$start_time = time();
class TimeLimitException extends Exception {}

// lambda uses $start_time global so it can reset
// the timer after the time limit is reached
register_tick_function(function() {
    global $start_time;
    if (time() - $start_time > 20) {
        echo 'Script execution halted. Took more than 20 seconds to execute', PHP_EOL;
        $start_time = time();
        throw new TimeLimitException();
    }
}, true);

try {
    // time limit will reset to here. Cannot jump to a label in a loop
    limit:

    while (1) {
        sleep(1);
        echo 'outer ';
        while (1) {
            echo 'inner ';
            sleep(2);
        }
    }
} catch (TimeLimitException $e) {
    echo 'time limit hit, jumping to label `limit`', PHP_EOL;
    goto limit;
}
like image 63
Josh J Avatar answered Nov 09 '22 15:11

Josh J


Actually, something like set_time_limit is a better approach.

Alternatively, if you just want to limit the includetime, do Threads.

class workerThread extends Thread {
    public function __construct(){
        $this->starttime=time();
    }

    public function run(){
        include_once 'onefile.php';
        include 'somefile.php';
        include 'somefile2.php';
        $this->done=true;
    }
    public function finished(){
        return $this->done || (time() - $this->starttime < 20)
    }
}
$worker=new workerThread();
$worker->start();
while(!$worker->finished()){}
like image 34
user2358582 Avatar answered Nov 09 '22 13:11

user2358582