# [RFC] Polling API Additions

- Thread: https://externals.io/message/132725
- Original archive: https://news-web.php.net/php.internals/132725
- Started by Jakub Zelenka on 2026-09-30T17:57:50+00:00
- Messages: 6
- RFC: Polling API Additions (Under discussion) — https://externals.io/rfc/poll_api_additions.md
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #132725 — Jakub Zelenka — 2026-09-30T17:57:50+00:00

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

Hi,

I would like to introduce the Polling API Additions RFC:

https://wiki.php.net/rfc/poll_api_additions

This is follow up to Polling API RFC.

Kind regards,

Jakub

---

## #132748 — Larry Garfield — 2026-10-01T13:28:08+00:00

URL: https://externals.io/message/132725#132748 · In reply to: #132725

> Hi,
>
> I would like to introduce the Polling API Additions RFC:
>
> https://wiki.php.net/rfc/poll_api_additions
>
> This is follow up to Polling API RFC.
>
> Kind regards,
>
> Jakub

While much of these two RFCs is over my head, I will reiterate the same point I made to Tim and Derick.  You clearly have a roadmap in mind.  The RFCs hint at that, and discuss some parts of it.  But what's still missing is a single reference point with the full plan, at whatever level of granularity you have right now.  Please please put something like that together, probably on the Wiki someplace that the RFCs can reference.

The work you're doing is incredibly important, and we really need to have a big picture view of the arc of your work so we can review it in the proper context.

--Larry Garfield

---

## #132749 — Sebastian Bergmann — 2026-10-01T13:41:39+00:00

URL: https://externals.io/message/132725#132749 · In reply to: #132725

Am 30.09.2026 um 19:57 schrieb Jakub Zelenka:
> I would like to introduce the Polling API Additions RFC:
> 
> https://wiki.php.net/rfc/poll_api_additions <https://wiki.php.net/rfc/ 
> poll_api_additions>

Thank you for this RFC!

As far as I can tell, it is an amazing improvement. Watchers that cannot 
outlive their descriptor, signals and child process exits as events, and 
timers in the context make Io\Poll a complete foundation for an event 
loop, without PECL extensions or userland workarounds.

I would echo Larry's request for the big picture. The RFCs hint at a 
roadmap, and a single wiki page outlining the full plan, at whatever level 
of detail exists today, that the RFCs could reference would help a lot.

Best,
Sebastian

-- 
Sebastian Bergmann                                 https://phpunit.expert

Stay up to date with PHPUnit: https://phpunit.expert/newsletter

---

## #132752 — Jakub Zelenka — 2026-10-01T14:02:27+00:00

URL: https://externals.io/message/132725#132752 · In reply to: #132748

Hi,

On Thu, Oct 1, 2026 at 3:30 PM Larry Garfield <larry@garfieldtech.com>
wrote:

> 
> > […]
>
> While much of these two RFCs is over my head, I will reiterate the same
> point I made to Tim and Derick.  You clearly have a roadmap in mind.  The
> RFCs hint at that, and discuss some parts of it.  But what's still missing
> is a single reference point with the full plan, at whatever level of
> granularity you have right now.  Please please put something like that
> together, probably on the Wiki someplace that the RFCs can reference.
>
> The work you're doing is incredibly important, and we really need to have
> a big picture view of the arc of your work so we can review it in the
> proper context.
>
>
If you are asking about a complete and detailed design doc for all 3 RFC's,
it can be found at
https://gist.github.com/bukka/87359261a4bfaa572ce43c93c0554b55 (I just
added a link to the RFC's).

There is really no roadmap except what is in those 3 RFC's (and more
details in that document). This particular RFC builds on existing Polling
API and introduces all bits that are needed to make it usable with IO Hooks
introduced in another RFC. The hooks RFC is all that is needed to allow
introduction of IO suspension points. The Ring RFC completes it with option
for IO offloading. There can be future implementation like Edmond's
scheduler that could make full use of this for the IO side of things. The
API was developed with this in mind but essentially it's an independent
project. The polling API additions are useful even without the IO Hooks as
those features are already requested by user space users of the API. If you
feel that some more details should be added to IO Hooks, please comment
there with a bit more specific info what exactly would you like to see
there.

Kind regards,

Jakub

---

## #132757 — Ilia — 2026-10-01T16:14:08+00:00

URL: https://externals.io/message/132725#132757 · In reply to: #132725

> I would like to introduce the Polling API Additions RFC:
>
> https://wiki.php.net/rfc/poll_api_additions
>

Hi Jakub,

Timers, notify and priority look good to me, and the deadline heap and
 `WNOWAIT` choices are the right ones. A few things from reading and
running the io_hooks_poc branch before a vote:

1. Please split the vote by group. Signals carry most of the risk and
   shouldn't hold back timers.

2. `exec()`, `system()`, `passthru()`, `shell_exec()` and backticks go through
   libc `popen()` and never reset the mask. With /bin/sh as bash the
   child gets `SIGTERM` blocked; with dash only exec-prefixed commands
   do. "The blocked mask does not leak into executed programs" needs a
   single choke point, not a list of call sites.

3. pcntl can unblock a watched signal behind the handle:
   pcntl_sigprocmask(SIG_UNBLOCK/SIG_SETMASK) directly, and
   `pcntl_signal()` via zend_sigaction(), which unblocks the signal it
   installs. In both cases the pcntl handler runs and the handle sees
   nothing, so "a handler installed with `pcntl_signal()` never runs
   while a handle for it is watched" doesn't hold with zend signals on.

4. While `SIGTERM` is watched, `sleep()` and blocking reads run to
   completion, and a script that never calls wait() exits 0: the
   shutdown drain records the signal into a handle that is then freed.
   Worth stating, and it's the main argument for the self-pipe model
   in your open issue.

5. onWatcherRemoved also fires for the script's own `fclose()` (your
   poll_weakhandle_on_watcher_removed.phpt relies on it), so the
   connection-table example comment is wrong.

6. The PoC changes wait() on EINTR from throwing FailedPollWaitException
   to restarting or returning []. I think that's right, but it changes
   the 8.6 API and should be in the RFC. A signal landing in wait()
   before the syscall still blocks it with the PHP handler pending; a
   php_io_interrupt_pending() check before blocking would close that.

7. ProcessHandle: new ProcessHandle($pid) for a non-child races pid
   reuse, and the exit probe uses waitid(P_PID) rather than P_PIDFD, so
   after an external reap it can read another process's status.
   getStatus() is a wait status on POSIX and an exit code on Windows,
   and non-null for non-children only on Windows.

8. TimerHandle: please specify the clock and that the deadline starts
   at add(), which is what the PoC does with zend_hrtime().

9. isExposed() and the in-use null from getStream() can't be observed
   through this RFC's API alone; they belong with IO hooks.

-- 
Ilia Alshanetsky
Technologist, CTO, Entrepreneur
E: ilia@ilia.ws
T: @iliaa
B: http://ilia.ws

---

## #132862 — tim@bastelstu.be — 2026-10-11T11:29:28+00:00

URL: https://externals.io/message/132725#132862 · In reply to: #132725

Hi


> I would like to introduce the Polling API Additions RFC:
> 
> https://wiki.php.net/rfc/poll_api_additions
> 
> This is follow up to Polling API RFC.

Thank you for your RFC. As I already mentioned off-list I'm very much 
looking forward to the next parts of the polling API.

I've given the RFC a full read now and have the following comments, many 
of which are questions intended to spark a discussion, instead of 
concrete fully-refined suggestions.

1. I agree with Ilia's suggestion to split the RFC into multiple scoped 
votes, even if everything is discussed at the same time for the “big 
picture”. The RFC itself already mentions “Every addition is useful on 
its own” in the introduction. This also allows to easily split off the 
parts that might need just a little more discussion. The “URI followup” 
for PHP 8.6 would be a good example. It started with 6 things, two were 
split off and the remaining 4 had a separate (primary) vote each.

2. Is the separate `WeakHandle` interface and classes necessary? Would 
it also be possible to do something like `new 
StreamPollHandle(WeakReference::create($stream))`? It would be 
unfortunate if it would be necessary to duplicate everything as “strong” 
and “weak”.

3. Can the RFC document the expected `callable` signature for 
`Context::onWatcherRemoved()` (e.g. is the callback `: void`, what 
parameters are passed to it?).

4. I'm not sure about the naming and namespacing of the `TimerHandle`. 
Putting it straight into `Io\Poll` would make the namespace very full. 
For Random\Engine and the currently discussed Time\Clock we put the 
implementations of the interface in a sub-namespace named after the 
interface (and dropped the `Handle` suffix). In contrast to 
`StreamPollHandle`, the `Handle` suffix on `TimerHandle` doesn't carry 
any additional meaning and I don't think it helps disambiguation when 
imported in an unqualified way. Not sure if `Io\Poll\Handle\Timer` is 
the correct choice. Perhaps it can also be just `Io\Timer` when the 
`Timer` is usable standalone, e.g. using a `Io\Timer::sleep()` method or 
similar - or it would be correctly placed in `Time\` similarly to 
Golang.

Even though I'm not 100% convinced by my suggestion, I wanted to put it 
out to allow discussing it. Perhaps someone else on this list has a good 
suggestion or reasoning based on my rough idea.

5. The RFC should explain if `getTimeout()` returns the constructor 
parameter directly - or if it returns the remaining timeout.

6. Would having a `TimerHandle::pause()` or `TimerHandle::stop()` or 
`TimerHandle::reset()` method be useful to allow modifying the timer 
without going through the Context?

7. As an aside: I'm happy that we could immediately find another use for 
`Duration` with the `TimerHandle`. This is a good indication for me that 
it was worth it getting it into 8.6 last minute to ensure a nice and 
consistent polling API :-)

8. For `TimerHandle`: Should the configured timeout and the periodic 
flag be exposed as (readonly) properties instead of methods? Those are 
effectively “properties” of the object in the English sense of the word.

9. Similarly to `TimerHandle` also for the `SignalHandle`: Would it 
theoretically be possible for the `SignalHandle` to act both as a 
standalone API and be usable with the polling API? Not sure if that 
makes sense. Is there perhaps precedent in other programming languages?

10. For `ProcessHandle` I don't think we should have both a regular 
constructor and named constructor. This makes discoverability worse, 
because the regular constructor doesn't show up in autocompletion for 
`ProcessHandle::from*`.

11. It is not unlikely that we want to introduce a new “Process” API to 
improve developer experience. Tying the `ProcessHandle` class to the 
existing `proc_open()` resources would be unfortunate when a new API 
with new concepts is then introduced. It will also not show up when 
autocompleting `proc_*()`. My suggestion would therefore be a 
`proc_get_poll_handle()` function ot similar that constructs the 
`ProcessHandle`, while keeping the integration contained in the 
`proc_*()' API.

12. For the `NotifyHandle`: Is it possible or does it make sense for it 
to support providing additional “metadata” as part of the notification, 
such as `->notify("hey, wake up")`, similarly to how the `ProcessHandle` 
provides the exit status.

13. The “RFC Impact” section is following an old template, and the 
ecosystem impact subsection is missing. Could you add some short note 
about the expected Impact for e.g. ReactPHP?

14. In the “RFC Impact” section the RFC says “SignalHandle is limited to 
the CLI SAPI in thread-safe builds”, which is ambiguous to me. Is this 
“SignalHandle only works in ZTS CLI. It does not work in NTS at all and 
does not work in ZTS FPM / FrankenPHP” or is this “SignalHandle works in 
all NTS. For ZTS only CLI is supported”? Based on the explanation of the 
`SignalHandle`, I assume it's the latter?

15. Seeing the examples: Can you clarify the behavior of 
`SignalHandle::getDelivered()`. Which previous call is meant? Is it the 
previous call to `SignalHandle::getDelivered()` or is it the previous 
call to `Context::wait()`? Would it make sense to make 
`SignalHandle::getDelivered()` return a generator instead to make it 
more explicit that the return value is only meant to be consumed once?

Best regards
Tim Düsterhus
