[php-src] PR #25135: Fix the WSAPoll backend of Io\Poll accepting handles that are not sockets

From: Date: Sun, 01 Nov 2026 19:08:30 +0000
Subject: [php-src] PR #25135: Fix the WSAPoll backend of Io\Poll accepting handles that are not sockets
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-40197@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/25135 Author: nicolas-grekas Found in [revoltphp/event-loop#135](https://github.com/revoltphp/event-loop/pull/135), where the Windows CI hangs on callbacks on STDOUT. WSAPoll() can only poll sockets, but the WSAPoll backend accepts any fd. Files and pipes give a CRT fd, so Context::add() succeeds for them. Then WSAPoll() reports POLLNVAL for them, or fails with WSAENOTSOCK when they're alone. In both cases wait() drops them and returns at once. The watcher is never reported: ```php // STDOUT is a pipe $ctx = new Io\Poll\Context(); $ctx->add(new StreamPollHandle(STDOUT), [Io\Poll\Event::Write]); // no exception $ctx->wait(); // returns [] at once, and again on every call ``` This PR checks the fd with getsockopt(SO_TYPE) in add(), the way stream_select() tells sockets apart on Windows. Anything else fails with ERROR_NOSUPPORT, as #23805 does for epoll. An event loop can then catch the FailedHandleAddException and fall back to stream_select(). Revolt doesn't pick its Io\Poll driver on Windows for now because of this. I left the WSAENOTSOCK branch of wait() as is. This branch now only sees sockets that were closed after being added. It drops those sockets like the poll backend drops POLLNVAL. /cc @bukka

« previous php.git-pulls (#40197) next »