Detecting a timeout for a block of code in PHP

后端 未结 9 1631
[愿得一人]
[愿得一人] 2021-02-02 16:44

Is there a way you can abort a block of code if it\'s taking too long in PHP? Perhaps something like:

//Set the max time to 2 seconds
$time = new TimeOut(2);
$ti         


        
相关标签:
9条回答
  • 2021-02-02 17:08

    You can also use a 2nd script that has the pause code in it that is executed via a curl call with a timeout set. The other obvious solution is to fix the cause of the pause.

    0 讨论(0)
  • 2021-02-02 17:11

    You can do this by forking the process, and then using the parent process to monitor the child process. pcntl_fork is a method that forks the process, so you have two nearly identical programs in memory running in parallel. The only difference is that in one process, the parent, pcntl_fork returns a positive integer which corresponds to the process id of the child process. And in the other process, the child, pcntl_fork returns 0.

    Here's an example:

    $pid = pcntl_fork();
    if ($pid == 0) {
        // this is the child process
    } else {
        // this is the parent process, and we know the child process id is in $pid
    }
    

    That's the basic structure. Next step is to add a process expiration. Your stuff will run in the child process, and the parent process will be responsible only for monitoring and timing the child process. But in order for one process (the parent) to kill another (the child), there needs to be a signal. Signals are how processes communicate, and the signal that means "you should end immediately" is SIGKILL. You can send this signal using posix_kill. So the parent should just wait 2 seconds then kill the child, like so:

    $pid = pcntl_fork();
    if ($pid == 0) {
        // this is the child process
        // run your potentially time-consuming method
    } else {
        // this is the parent process, and we know the child process id is in $pid
        sleep(2); // wait 2 seconds
        posix_kill($pid, SIGKILL); // then kill the child
    }
    
    0 讨论(0)
  • 2021-02-02 17:11

    Cooked this up in about two minutes, I forgot to call $time->startTime(); so I don't really know exactly how long it took ;)

    class TimeOut{
        public function __construct($time=0)
        {
            $this->limit = $time;
        }
    
        public function startTime()
        {
            $this->old = microtime(true);
        }
    
        public function checkTime()
        {
            $this->new = microtime(true);
        }
    
        public function timeExpired()
        {
            $this->checkTime();
            return ($this->new - $this->old > $this->limit);
        }
    
    }
    

    And the demo.

    I don't really get what your endTime() call does, so I made checkTime() instead, which also serves no real purpose but to update the internal values. timeExpired() calls it automatically because it would sure stink if you forgot to call checkTime() and it was using the old times.

    0 讨论(0)
提交回复
热议问题