# Graceful timeout

- Thread: https://externals.io/message/110188
- Original archive: https://news-web.php.net/php.internals/110188
- Started by David Rodrigues on 2020-05-16T17:41:32+00:00
- Messages: 6
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #110188 — David Rodrigues — 2020-05-16T17:41:32+00:00

URL: https://externals.io/message/110188#110188

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 — Derick Rethans — 2020-05-16T18:15:23+00:00

URL: https://externals.io/message/110188#110190 · In reply to: #110188

Hi David,



> 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 — tyson andre — 2020-05-16T18:55:58+00:00

URL: https://externals.io/message/110188#110192 · In reply to: #110190

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

---

## #110193 — Jakob Givoni — 2020-05-16T19:34:45+00:00

URL: https://externals.io/message/110188#110193 · In reply to: #110188

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

---

## #110194 — Niklas Keller — 2020-05-16T20:29:48+00:00

URL: https://externals.io/message/110188#110194 · In reply to: #110188

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

---

## #110205 — johannes@schlueters.de — 2020-05-18T15:44:51+00:00

URL: https://externals.io/message/110188#110205 · In reply to: #110190

> 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
