Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ PHP NEWS
. Fixed chown() and lchown() failing to resolve user names in ZTS builds
when getpwnam_r() needs a larger buffer. (Ilia Alshanetsky)

- Streams:
. Fixed bug GH-24173 (Sockets from synchronous stream_socket_client() are
left in non-blocking mode on Windows). (vibbow)

22 Oct 2026, PHP 8.4.27

- BCMath:
Expand Down
25 changes: 25 additions & 0 deletions ext/standard/tests/streams/gh24173.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
GH-24173 (Sockets from synchronous stream_socket_client() are left in non-blocking mode on Windows)
--EXTENSIONS--
sockets
--SKIPIF--
<?php
if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only');
?>
--FILE--
<?php
$srv = stream_socket_server('tcp://127.0.0.1:0', $errno, $errstr);
$client = stream_socket_client('tcp://' . stream_socket_get_name($srv, false), $errno, $errstr, 5);
$conn = stream_socket_accept($srv);

$sock = socket_import_stream($client);
socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 0, 'usec' => 100000]);

// No data is sent: a blocking socket waits and times out, while a
// non-blocking one fails at once with WSAEWOULDBLOCK.
var_dump(@socket_read($sock, 10));
var_dump(socket_last_error($sock) === SOCKET_ETIMEDOUT);
?>
--EXPECT--
bool(false)
bool(true)
4 changes: 3 additions & 1 deletion main/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,10 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
typedef u_long php_non_blocking_flags_t;
# define SET_SOCKET_BLOCKING_MODE(sock, save) \
save = TRUE; ioctlsocket(sock, FIONBIO, &save)
/* Winsock cannot query the current mode; callers pass freshly created
* (blocking) sockets, so restore to blocking. */
# define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
ioctlsocket(sock, FIONBIO, &save)
save = FALSE; ioctlsocket(sock, FIONBIO, &save)
#else
typedef int php_non_blocking_flags_t;
# define SET_SOCKET_BLOCKING_MODE(sock, save) \
Expand Down
Loading