From 0173f33a57f847134ce8ce722b378d1a0c6279ee Mon Sep 17 00:00:00 2001 From: Louis-Arnaud Date: Thu, 3 Sep 2026 12:51:13 +0200 Subject: [PATCH 1/3] socket_select(): say that the array keys are preserved The page already warns that the arrays are modified on exit, but not that an entry that stays keeps the key it came in with, which is what callers need in order to map a ready socket back to whatever it belongs to. stream_select() documents it; php_sock_array_from_fd_set() reinserts each surviving entry under its original key, integer or string, so the two functions agree. Fixes: #5787 --- reference/sockets/functions/socket-select.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/sockets/functions/socket-select.xml b/reference/sockets/functions/socket-select.xml index 6ce55910d45a..79324d5b7f98 100644 --- a/reference/sockets/functions/socket-select.xml +++ b/reference/sockets/functions/socket-select.xml @@ -83,10 +83,11 @@ - + On exit, the arrays are modified to indicate which socket actually changed status. - + The original keys of the &array;s are preserved. + You do not need to pass every array to From 115328499d2a73912041be3c8b0a421fabe68dd9 Mon Sep 17 00:00:00 2001 From: Louis-Arnaud Date: Thu, 3 Sep 2026 13:06:07 +0200 Subject: [PATCH 2/3] socket_select(): fix the surrounding page while we are here The page said the arrays could be left out. They cannot: the function takes at least four arguments, an uninteresting one has to be an empty array or null, and all three empty raises a ValueError. The microseconds entry was an empty paragraph, and the notes carried a sentence that never parsed ("If you read/write to a socket returns in the arrays"). Also stream_select() in seealso, since the two functions are each other's counterpart, and the usual typos: happens.On, zero , causing, Due a limitation, socket_select return. --- reference/sockets/functions/socket-select.xml | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/reference/sockets/functions/socket-select.xml b/reference/sockets/functions/socket-select.xml index 79324d5b7f98..67c07bb30283 100644 --- a/reference/sockets/functions/socket-select.xml +++ b/reference/sockets/functions/socket-select.xml @@ -61,23 +61,24 @@ seconds - + The seconds and microseconds together form the timeout parameter. The timeout is an upper bound on the amount of time - elapsed before socket_select return. - seconds may be zero , causing + elapsed before socket_select returns. + seconds may be zero, causing socket_select to return immediately. This is useful for polling. If seconds is &null; (no timeout), socket_select can block indefinitely. - + microseconds - - + + See seconds description. + @@ -89,16 +90,16 @@ The original keys of the &array;s are preserved. - - You do not need to pass every array to - socket_select. You can leave it out and use an - empty array or &null; instead. Also do not forget that those arrays are - passed by reference and will be modified after + + The three arrays all have to be passed, but an array that is of no + interest can be an empty &array; or &null;; at least one of them must be + a non-empty &array;. They are passed + by reference and are modified once socket_select returns. - + - Due a limitation in the current Zend Engine it is not possible to pass a + Due to a limitation in the current Zend Engine it is not possible to pass a constant modifier like &null; directly as a parameter to a function which expects this parameter to be passed by reference. Instead use a temporary variable or an expression with the leftmost member being a @@ -120,13 +121,13 @@ socket_select($r, $w, $e, 0); &reftitle.returnvalues; - + On success socket_select returns the number of sockets contained in the modified arrays, which may be zero if - the timeout expires before anything interesting happens.On error &false; + the timeout expires before anything interesting happens. On error &false; is returned. The error code can be retrieved with socket_last_error. - + Be sure to use the === operator when checking for an @@ -203,10 +204,9 @@ if ($num_changed_sockets === false) { - If you read/write to a socket returns in the arrays be aware that - they do not necessarily read/write the full amount of data you have - requested. Be prepared to even only be able to read/write a single - byte. + When reading from or writing to a socket returned in the arrays, be + aware that the full amount of data requested is not necessarily read + or written. Be prepared for as little as a single byte. @@ -223,14 +223,13 @@ if ($num_changed_sockets === false) { &reftitle.seealso; - - - socket_read - socket_write - socket_last_error - socket_strerror - - + + socket_read + socket_write + socket_last_error + socket_strerror + stream_select + From 8b2a9906fe0869c1b9204dd62eb981fe78b42145 Mon Sep 17 00:00:00 2001 From: Louis-Arnaud Date: Thu, 3 Sep 2026 13:10:23 +0200 Subject: [PATCH 3/3] stream_select(): it is not equivalent to socket_select() The page claimed the two functions operate identically apart from what they act on. They do not. A negative timeout is a ValueError here and a warning plus false there, an invalid element is skipped here and a TypeError there, and microseconds is nullable only here. The larger difference had no mention anywhere: when a stream already has buffered data on the PHP side, select() is never called, and the write and except arrays come back empty without having been looked at. A caller watching for writability silently gets nothing. Also socket_select() in seealso, and the same unparseable sentence about partial reads that the socket_select() page carries. --- reference/stream/functions/stream-select.xml | 39 +++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/reference/stream/functions/stream-select.xml b/reference/stream/functions/stream-select.xml index ebdac059c391..6ef1a7914e8a 100644 --- a/reference/stream/functions/stream-select.xml +++ b/reference/stream/functions/stream-select.xml @@ -16,11 +16,14 @@ intnullseconds intnullmicroseconds&null; - - The stream_select function accepts arrays of streams and - waits for them to change status. Its operation is equivalent to that of - the socket_select function except in that it acts on streams. - + + The stream_select function accepts arrays of streams + and waits for them to change status. It is the stream counterpart of + socket_select, but the two do not behave alike in + every respect: they report invalid arguments differently, and + stream_select can return without consulting the + operating system at all, as described in the notes below. + @@ -219,18 +222,27 @@ if (false === stream_select($r, $w, $e, 0)) { - - If you read/write to a stream returned in the arrays be aware that - they do not necessarily read/write the full amount of data you have - requested. Be prepared to even only be able to read/write a single - byte. - + + When reading from or writing to a stream returned in the arrays, be aware + that the full amount of data requested is not necessarily read or + written. Be prepared for as little as a single byte. + - + Some streams (like zlib) cannot be selected by this function. - + + + + + A stream that already holds buffered data on the PHP side is reported as + ready without the underlying select() call being made. + When that happens the write and + except arrays are emptied without having been + examined, so a stream that was ready for writing goes unreported and the + return value counts the readable streams only. + Windows compatibility @@ -250,6 +262,7 @@ if (false === stream_select($r, $w, $e, 0)) { &reftitle.seealso; stream_set_blocking + socket_select