On Wed, Sep 30, 2026 at 2:11 PM Jakub Zelenka <[email protected]> wrote:

> I would like to introduce a new IO Hooks and Operations RFC:
>
> https://wiki.php.net/rfc/io_hooks
>
>
Hi Jakub,

My concern is the safety model. With a provider installed every hooked
call becomes a suspension point inside C code written assuming no PHP
runs during IO. The branch guards the stream, curl, Socket,
XMLReader/XMLWriter and three mysqli entry points. With only the Poll
queue I hit or traced:

- DOMDocument::save() to a pipe, FIFO or ftp:// target: loadXML() or
  removeChild() from another Fiber frees the tree mid-serialize
  (valgrind: reads of the doc freed by loadXML; removeChild segfaults).
- hash_update_stream(): hash_final() from another Fiber NULLs
  hash->context under the read loop (segfault).
- libxml_set_streams_context() during a suspended http read frees the
  context the redirect then reuses.
- mysqlnd shared across Fibers: an unbuffered result can be freed under
  fetch_row, a persistent PDO liveness check can free the connection,
  and pdo_mysql has no guard at all.
- With Files, an include suspends inside opcache's compile window, so
  classes declared meanwhile end up in the cached script.

Guarding objects one at a time won't converge, and third-party
extensions never opted in. I'd flip the default: hooked calls run
synchronously unless the call site declares itself suspension safe.

>From running the branch:

1. Pipes are not syscall first, so a 10-byte top-level fwrite(STDOUT)
   to a pipe, or sleep(), under the RFC's Scheduler throws FiberError.
   The main flow needs a defined rule.
2. Under a provider STDIN/STDOUT get O_NONBLOCK on the shared file
   description; other processes and system() children see it, and it
   survives kill -9. Without one, a proc_open child given a socket as
   stdin gets EAGAIN from dd. Neither is in the BC section.
3. An exception unwinding past a registered stream skips remove(), and
   the next socket on that fd number is never re-armed.
4. Two Fibers flock()ing one file deadlock the process.
5. A provider declaring DirectData can complete Write/Send as Done
   without doing anything. I'd keep Files/DirectData/DirectAccept out of
   the userland API until the Ring RFC passes.

Could the hooks be split out of the branch into their own PR? At 23k
lines with the Ring and the Poll additions, it's hard to review.


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

Reply via email to