Graceful timeout

php.internals

David Rodrigues

6 years ago
Hello! Currently we can use set_time_limit() to specify that our script will run by some seconds before we get "fatal error: maximum execution time of 1 second exceeded". And we can't catch it and keep running. I believe that it is interesting to create a function that is able to limit processing and stop when the time limit is recovered. $completeRun = set_time_limit_callback(function () { sleep(2); }, 1); var_dump($completeRun); Where $completeRun will be TRUE only if callback could run until it returns, and FALSE if timeout. It should be very useful when we need works with external resources, like RESTful, where timeout can occur and we need a better way to work with that. Or when we have few seconds to run a process. What do you think? Atenciosamente, David Rodrigues

Derick Rethans

6 years ago
Hi David, On Sat, 16 May 2020, David Rodrigues wrote:
> Currently we can use set_time_limit() to specify that our script will > run by some seconds before we get "fatal error: maximum execution time > of 1 second exceeded". And we can't catch it and keep running.
You can set-up a shutdown handler though, which will get called.
> > I believe that it is interesting to create a function that is able to > limit processing and stop when the time limit is recovered. > > $completeRun = set_time_limit_callback(function () { > sleep(2); > }, 1);
sleep(2) should not trigger a 1 second timeout. Currently the time counted for max_execution_time timeouts is CPU time, not wall time. You can probably implement this already with PHP's tick functionality (https://www.php.net/manual/en/function.register-tick-function.php), as long as the code in the anonymous function does PHP statements/function calls. If your problem is waiting for an external resource to be available (database call, http call), then instead you should be able to use functionality of these services to handle your timeouts. cheers, Derick
-- PHP 7.4 Release Manager Host of PHP Internals News: https://phpinternals.news Like Xdebug? Consider supporting me: https://xdebug.org/support https://derickrethans.nl | https://xdebug.org | https://dram.io twitter: @derickr and @xdebug

tyson andre

6 years ago
Hi David, > You can probably implement this already with PHP's tick functionality (https://www.php.net/manual/en/function.register-tick-function.php), as > long as the code in the anonymous function does PHP statements/function > calls. > > If your problem is waiting for an external resource to be available > (database call, http call), then instead you should be able to use > functionality of these services to handle your timeouts. If pcntl is available for your OS (not available on Windows), you can also use pcntl_async_signals() to allow receiving signals at any time, pcntl_alarm() to send a signal at a given number of seconds from then, and throw a custom exception from pcntl_signal() for SIGALRM. ticks() is limited - Every file would need to declare ticks=1 as of php 7.0, or you might get delayed in the files that didn't. Supporting a cross-platform form of pcntl_alarm() might be a better abstraction, but I don't have a strong use case for either of those. When implementing it, you'd need to ensure it didn't interfere with php's internal time limit implementations or signal handlers in an undesirable way (not something I'm deeply familiar with). That would also need to enable the checks that pcntl_async_signals(true) does. https://www.php.net/manual/en/function.pcntl-alarm.php https://www.php.net/manual/en/function.pcntl-async-signals.php https://www.php.net/manual/en/function.pcntl-signal.php - Tyson

Johannes Schlueter

6 years ago
On Sat, 2020-05-16 at 19:15 +0100, Derick Rethans wrote:
> sleep(2) should not trigger a 1 second timeout. Currently the time > counted for max_execution_time timeouts is CPU time, not wall time.
I might remember wrongly, but I think on Windows it uses wall time. One thing to consider when caring about that platform. johannes

Jakob Givoni

6 years ago
On Sat, 16 May 2020 at 19:42, David Rodrigues <david.proweb@gmail.com> wrote:
> Hello! > > Currently we can use set_time_limit() to specify that our script will run > by some seconds before we get "fatal error: maximum execution time of 1 > second exceeded". And we can't catch it and keep running. > > I believe that it is interesting to create a function that is able to limit > processing and stop when the time limit is recovered. > > $completeRun = set_time_limit_callback(function () { > sleep(2); > }, 1); > > var_dump($completeRun); > > Where $completeRun will be TRUE only if callback could run until it > returns, and FALSE if timeout. > > It should be very useful when we need works with external resources, like > RESTful, where timeout can occur and we need a better way to work with > that. Or when we have few seconds to run a process. > > What do you think? > > > Atenciosamente, > David Rodrigues
Hi David! So you’d like to be able to set a simple timeout on any function call. I was able to do that with register_tick_function (first time I heard about it!) with a function that throws an exception when the time’s up and then surrounding the function call in try/catch. This could probably be turned into a userland “library”. I’m not sure how well it would work with real world code though. For sure, timeouts on http calls must be set on the client handler itself. Best, Jakob

Niklas Keller

6 years ago
Hey David, I guess you're looking for a preemptive timeout. I guess an alarm signal and PHP's async signal handling will be your best bet here. In case you're looking for a cooperative timeout, https://amphp.org/ and it's `Amp\Promise\timeout()` / `TimeoutCancellationToken` might be helpful. Best, Niklas Am Sa., 16. Mai 2020 um 19:41 Uhr schrieb David Rodrigues < david.proweb@gmail.com>: