# Switching max_execution_time from CPU time to wall-clock time and from SIGPROF to SIGALRM

- Thread: https://externals.io/message/123331
- Original archive: https://news-web.php.net/php.internals/123331
- Started by Arnaud Le Blanc on 2024-05-17T13:47:03+00:00
- Messages: 10
- 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

---

## #123331 — Arnaud Le Blanc — 2024-05-17T13:47:03+00:00

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

Hi internals,

There is an issue with max_execution_time on MacOS, probably only
MacOS 14 on Apple Silicon, that causes timeouts to fire too early [1].
max_execution_time is implemented with setitimer(ITIMER_PROF) on this
platform, and the `SIGPROF` signal is delivered too early for some
reason. Switching to ITIMER_REAL appears to fix the issue, and Manuel
Kress opened a PR [3].

Are there objections against switching to ITIMER_REAL on MacOS (Apple
Silicon only) in all currently supported PHP versions? (next 8.2.x,
8.3.x, 8.x)

Apart from fixing the issue, this would introduce the following minor
breaking changes:

- max_execution_time on MacOS would be based on wall-clock time rather
than CPU time, so the time spent in I/O, `sleep()`, and syscalls in
general would count towards the max_execution_time
- The `SIGALRM` signal would be used instead of the `SIGPROF` signal
(using `SIGALRM` conflicts with `pcntl_alarm()`, but `SIGPROF` conflicts
with profilers). As noted by Dmitry, it also conflicts with `sleep()` on
some platforms, however this should be safe on MacOS.

Currently max_execution_time is based on wall-clock time on ZTS and
Windows, and CPU time otherwise. On Linux and FreeBSD, wall-clock time
can also be used when building with
--enable-zend-max-execution-timers. Máté proposed to add a wall-clock
based timeout in the past [2] but the discussion has stalled. Any
thoughts about eventually switching other platforms to wall-clock
timeouts in the next 8.x ?

TL;DR:
- Any objection about using wall-clock max_execution_time and `SIGALRM` 
on MacOS Apple Silicon in all supported versions?
- Thoughts about using wall-clock timeouts on all platforms in the next 8.x ?

[1] https://github.com/php/php-src/issues/12814
[2] https://github.com/php/php-src/pull/6504
[3] https://github.com/php/php-src/pull/13567

Best Regards,
Arnaud

---

## #123332 — Robert Landers — 2024-05-17T14:10:26+00:00

URL: https://externals.io/message/123331#123332 · In reply to: #123331

>
> Hi internals,
>
> There is an issue with max_execution_time on MacOS, probably only
> MacOS 14 on Apple Silicon, that causes timeouts to fire too early [1].
> max_execution_time is implemented with setitimer(ITIMER_PROF) on this
> platform, and the `SIGPROF` signal is delivered too early for some
> reason. Switching to ITIMER_REAL appears to fix the issue, and Manuel
> Kress opened a PR [3].
>
> Are there objections against switching to ITIMER_REAL on MacOS (Apple
> Silicon only) in all currently supported PHP versions? (next 8.2.x,
> 8.3.x, 8.x)
>
> Apart from fixing the issue, this would introduce the following minor
> breaking changes:
>
> - max_execution_time on MacOS would be based on wall-clock time rather
> than CPU time, so the time spent in I/O, `sleep()`, and syscalls in
> general would count towards the max_execution_time
> - The `SIGALRM` signal would be used instead of the `SIGPROF` signal
> (using `SIGALRM` conflicts with `pcntl_alarm()`, but `SIGPROF` conflicts
> with profilers). As noted by Dmitry, it also conflicts with `sleep()` on
> some platforms, however this should be safe on MacOS.
>
> Currently max_execution_time is based on wall-clock time on ZTS and
> Windows, and CPU time otherwise. On Linux and FreeBSD, wall-clock time
> can also be used when building with
> --enable-zend-max-execution-timers. Máté proposed to add a wall-clock
> based timeout in the past [2] but the discussion has stalled. Any
> thoughts about eventually switching other platforms to wall-clock
> timeouts in the next 8.x ?
>
> TL;DR:
> - Any objection about using wall-clock max_execution_time and `SIGALRM` 
> on MacOS Apple Silicon in all supported versions?
> - Thoughts about using wall-clock timeouts on all platforms in the next 8.x ?
>
> [1] https://github.com/php/php-src/issues/12814
> [2] https://github.com/php/php-src/pull/6504
> [3] https://github.com/php/php-src/pull/13567
>
> Best Regards,
> Arnaud

This sounds like a bug with Mac vs. a PHP issue. That being said, the
biggest issue between changing these clocks is that ITIMER_PROF is
(practically, but not explicitly) monotonic. ITIMER_REAL can go
backwards (NTP clock adjustments) which might have interesting
side-effects if the clock is adjusted.

The problem might actually be using ITIMER_PROF, which "Measures CPU
time used by the process, including both user space and kernel space"
and usage of sockets/threads might give an "accelerated" value while
maybe ITIMER_VIRTUAL is the one we should be using since it "Measures
CPU time used by the process (user space)" which won't count kernel
timings.

Robert Landers
Software Engineer
Utrecht NL

---

## #123336 — Calvin Buckley — 2024-05-17T17:42:07+00:00

URL: https://externals.io/message/123331#123336 · In reply to: #123331

> 
> Hi internals,
> 
> There is an issue with max_execution_time on MacOS, probably only
> MacOS 14 on Apple Silicon, that causes timeouts to fire too early [1].
> max_execution_time is implemented with setitimer(ITIMER_PROF) on this
> platform, and the `SIGPROF` signal is delivered too early for some
> reason. Switching to ITIMER_REAL appears to fix the issue, and Manuel
> Kress opened a PR [3].
> 
> Are there objections against switching to ITIMER_REAL on MacOS (Apple
> Silicon only) in all currently supported PHP versions? (next 8.2.x,
> 8.3.x, 8.x)
> 
> Apart from fixing the issue, this would introduce the following minor
> breaking changes:
> 
> - max_execution_time on MacOS would be based on wall-clock time rather
> than CPU time, so the time spent in I/O, `sleep()`, and syscalls in
> general would count towards the max_execution_time
> - The `SIGALRM` signal would be used instead of the `SIGPROF` signal
> (using `SIGALRM` conflicts with `pcntl_alarm()`, but `SIGPROF` conflicts
> with profilers). As noted by Dmitry, it also conflicts with `sleep()` on
> some platforms, however this should be safe on MacOS.
> 
> Currently max_execution_time is based on wall-clock time on ZTS and
> Windows, and CPU time otherwise. On Linux and FreeBSD, wall-clock time
> can also be used when building with
> --enable-zend-max-execution-timers. Máté proposed to add a wall-clock
> based timeout in the past [2] but the discussion has stalled. Any
> thoughts about eventually switching other platforms to wall-clock
> timeouts in the next 8.x ?
> 
> TL;DR:
> - Any objection about using wall-clock max_execution_time and `SIGALRM` 
> on MacOS Apple Silicon in all supported versions?
> - Thoughts about using wall-clock timeouts on all platforms in the next 8.x ?
> 
> [1] https://github.com/php/php-src/issues/12814
> [2] https://github.com/php/php-src/pull/6504
> [3] https://github.com/php/php-src/pull/13567
> 
> Best Regards,
> Arnaud

FWIW, Cygwin and IBM i are also using wall time, because these platforms
don't do execution time. IIRC, the difference between platforms with how
max_execution_time is counted doesn't seem to be documented last I checked.

---

## #123379 — Arnaud Le Blanc — 2024-05-21T12:39:01+00:00

URL: https://externals.io/message/123331#123379 · In reply to: #123332

Hi Robert,

> This sounds like a bug with Mac vs. a PHP issue.

This is what I believe as well. FWIW I was able to reproduce the issue
outside of PHP [2]. I've reported the bug to Apple, but I don't expect
it to be fixed quickly, if at all.

> That being said, the
> biggest issue between changing these clocks is that ITIMER_PROF is
> (practically, but not explicitly) monotonic. ITIMER_REAL can go
> backwards (NTP clock adjustments) which might have interesting
> side-effects if the clock is adjusted.

Good point. Do you have references about ITIMER_REAL using a
non-monotonic clock, besides the lack of specification regarding the
clock? Based on experiments and the code [1], I think that ITIMER_REAL
uses a monotonic clock on MacOS. It's not ideal to rely on that, and
we should use a better specified timer mechanism if we eventually
switch to wall-clock time on all platforms, but it seems reasonable as
a workaround for the ITIMER_PROF bug on MacOS/Apple Silicon.

> The problem might actually be using ITIMER_PROF, which "Measures CPU
> time used by the process, including both user space and kernel space"
> and usage of sockets/threads might give an "accelerated" value while
> maybe ITIMER_VIRTUAL is the one we should be using since it "Measures
> CPU time used by the process (user space)" which won't count kernel
> timings.

Unfortunately ITIMER_VIRTUAL is not really useful as a
max_execution_time implementation as it will basically never fire in a
syscall-heavy workload. E.g. after replacing ITIMER_PROF by
ITIMER_VIRTUAL in [2], the program runs for well over the specified
time before receiving a signal, despite consuming a considerable
amount of resources.

[1] https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_time.c#L432
[2] https://gist.github.com/arnaud-lb/012195a2fe4d3a2c1bff530a73ae6b11

Best Regards,
Arnaud

---

## #123380 — Arnaud Le Blanc — 2024-05-21T12:48:52+00:00

URL: https://externals.io/message/123331#123380 · In reply to: #123336

Hi Calvin,

> FWIW, Cygwin and IBM i are also using wall time, because these platforms
> don't do execution time.

Thank you for the additional info.

> IIRC, the difference between platforms with how
> max_execution_time is counted doesn't seem to be documented last I checked.

Currently the max_execution_time documentation has a note about that,
but it only mentions Windows:

> https://www.php.net/manual/en/info.configuration.php#ini.max-execution-time
> On non Windows systems, the maximum execution time is not affected by system calls, stream operations etc. Please see the `set_time_limit()` function for more details.

Best Regards,
Arnaud

---

## #123382 — kevin@dunglas.fr — 2024-05-21T15:53:27+00:00

URL: https://externals.io/message/123331#123382 · In reply to: #123380

Hello,

I'm in favor of merging Arnaud's patch for macOS while waiting for a better
solution like relying on Grand Central Dispatch or another non-signal-based
solution (https://github.com/php/php-src/pull/13468), which would allow
max_execution_time to work with ZTS builds on mac as well.

I'm also in favor of using wall-clock time wherever possible (disclaimer:
I'm the original author of this feature for Linux and FreeBSD).

Best,

---

## #123383 — Rob Landers — 2024-05-21T15:59:34+00:00

URL: https://externals.io/message/123331#123383 · In reply to: #123379

> Hi Robert,
> 
> > […]
> 
> This is what I believe as well. FWIW I was able to reproduce the issue
> outside of PHP [2]. I've reported the bug to Apple, but I don't expect
> it to be fixed quickly, if at all.
> 
> > […]
> 
> Good point. Do you have references about ITIMER_REAL using a
> non-monotonic clock, besides the lack of specification regarding the
> clock? Based on experiments and the code [1], I think that ITIMER_REAL
> uses a monotonic clock on MacOS. It's not ideal to rely on that, and
> we should use a better specified timer mechanism if we eventually
> switch to wall-clock time on all platforms, but it seems reasonable as
> a workaround for the ITIMER_PROF bug on MacOS/Apple Silicon.

That was my only concern. That being said, I’m all in favor of wall-clock time, personally. It’s much easier to reason about. 

> 
> > […]
> 
> Unfortunately ITIMER_VIRTUAL is not really useful as a
> max_execution_time implementation as it will basically never fire in a
> syscall-heavy workload. E.g. after replacing ITIMER_PROF by
> ITIMER_VIRTUAL in [2], the program runs for well over the specified
> time before receiving a signal, despite consuming a considerable
> amount of resources.
> 
> [1] https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_time.c#L432
> [2] https://gist.github.com/arnaud-lb/012195a2fe4d3a2c1bff530a73ae6b11
> 
> Best Regards,
> Arnaud
> 

— Rob

---

## #123386 — kontakt@beberlei.de — 2024-05-21T19:05:22+00:00

URL: https://externals.io/message/123331#123386 · In reply to: #123331

> Hi internals,
>
> There is an issue with max_execution_time on MacOS, probably only
> MacOS 14 on Apple Silicon, that causes timeouts to fire too early [1].
> max_execution_time is implemented with setitimer(ITIMER_PROF) on this
> platform, and the `SIGPROF` signal is delivered too early for some
> reason. Switching to ITIMER_REAL appears to fix the issue, and Manuel
> Kress opened a PR [3].
>
> Are there objections against switching to ITIMER_REAL on MacOS (Apple
> Silicon only) in all currently supported PHP versions? (next 8.2.x,
> 8.3.x, 8.x)
>
> Apart from fixing the issue, this would introduce the following minor
> breaking changes:
>
> - max_execution_time on MacOS would be based on wall-clock time rather
> than CPU time, so the time spent in I/O, `sleep()`, and syscalls in
> general would count towards the max_execution_time
> - The `SIGALRM` signal would be used instead of the `SIGPROF` signal
> (using `SIGALRM` conflicts with `pcntl_alarm()`, but `SIGPROF` conflicts
> with profilers). As noted by Dmitry, it also conflicts with `sleep()` on
> some platforms, however this should be safe on MacOS.
>
> Currently max_execution_time is based on wall-clock time on ZTS and
> Windows, and CPU time otherwise. On Linux and FreeBSD, wall-clock time
> can also be used when building with
> --enable-zend-max-execution-timers. Máté proposed to add a wall-clock
> based timeout in the past [2] but the discussion has stalled. Any
> thoughts about eventually switching other platforms to wall-clock
> timeouts in the next 8.x ?
>
> TL;DR:
> - Any objection about using wall-clock max_execution_time and `SIGALRM` 
> on MacOS Apple Silicon in all supported versions?
> - Thoughts about using wall-clock timeouts on all platforms in the next
> 8.x ?
>
> [1] https://github.com/php/php-src/issues/12814
> [2] https://github.com/php/php-src/pull/6504
> [3] https://github.com/php/php-src/pull/13567
>
> Best Regards,
> Arnaud
>

For reference: There is also this RFC for max_execution_wall_time that was
discussed four years ago. https://externals.io/message/112492#112492

---

## #123420 — tim@bastelstu.be — 2024-05-23T18:26:21+00:00

URL: https://externals.io/message/123331#123420 · In reply to: #123379

Hi


> This is what I believe as well. FWIW I was able to reproduce the issue
> outside of PHP [2]. I've reported the bug to Apple, but I don't expect
> it to be fixed quickly, if at all.

Is the bug report public / can you provide a link to it?

Best regards
Tim Düsterhus

---

## #123424 — Arnaud Le Blanc — 2024-05-23T19:15:04+00:00

URL: https://externals.io/message/123331#123424 · In reply to: #123420

Hi Tim,

The report submitted to Apple via Feedback Assistant is not public,
but here is a mirror:
https://openradar.appspot.com/radar?id=5583058442911744

Best regards,
Arnaud


>
> Hi
>
> 
> > […]
>
> Is the bug report public / can you provide a link to it?
>
> Best regards
> Tim Düsterhus
