Graceful timeout

  110188
May 16, 2020 17:41 david.proweb@gmail.com (David Rodrigues)
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
  110190
May 16, 2020 18:15 derick@php.net (Derick Rethans)
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
  110192
May 16, 2020 18:55 tysonandre775@hotmail.com (tyson andre)
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
  110205
May 18, 2020 15:44 johannes@schlueters.de (Johannes =?ISO-8859-1?Q?Schl=FCter?=)
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
  110193
May 16, 2020 19:34 jakob@givoni.dk (Jakob Givoni)
On Sat, 16 May 2020 at 19:42, David Rodrigues 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
> >
  110194
May 16, 2020 20:29 me@kelunik.com (Niklas Keller)
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>:

> 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 >