mirror of
https://github.com/php/php-src.git
synced 2026-10-29 10:22:06 +08:00
StreamPollHandle took the descriptor through the select cast. On a TLS stream that cast reads: it moves what OpenSSL holds decrypted into the stream buffer so that stream_select() can report it. Adding a watcher to an Io\Poll\Context therefore read from the stream, filled the buffer of a stream set unbuffered with stream_set_read_buffer() and changed unread_bytes. That is not how the poll API should behave. Adding a handle is a registration and must leave the stream as it found it, and the data that moved was not reported by the watcher anyway, as bytes held by the stream layer are not readiness of the descriptor. A new cast PHP_STREAM_AS_FD_FOR_POLL returns the descriptor and nothing else. The socket, TLS, plain and pgsql wrappers answer it, a userspace wrapper sees it as STREAM_CAST_FOR_SELECT and the stream it returns is cast the same way, and a filtered stream allows it like the select cast. StreamPollHandle uses it, so adding a TLS stream leaves its buffer and unread_bytes as they were. The select cast and stream_select() are unchanged. This is fixed in 8.6 because the API is new there and this is the behaviour it should ship with. Keeping a read inside the registration would complicate things later: once reads on a TLS stream can suspend, the cast would become a nested read on a stream with an operation in flight, and changing the cast then would change the visible behaviour of a released API.