Skip to content

Commit ec8db37

Browse files
vibbowclaude
andcommitted
Fix GH-24171: Slow stream_socket_client() connect on Windows
On Windows, php_network_connect_socket() calls getsockopt(SO_ERROR) right after select() reports that the non-blocking connect completed. Inside mswsock, SockIsSocketConnected() can then race with mswsock's own async thread and wait on an internal completion port with a 10 ms timeout, so the call often blocks for 10-25 ms. Winsock reports a successful non-blocking connect in writefds and a failed one in exceptfds, and we already poll for POLLOUT|POLLPRI. So when only POLLOUT is set, the connect has succeeded and getsockopt() can be skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent c792847 commit ec8db37

2 files changed

Lines changed: 10 additions & 0 deletions

File tree

‎NEWS‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ PHP NEWS
105105
- Streams:
106106
. Applied the so_linger, so_rcvbuf and so_sndbuf context options to unix
107107
sockets. (David Carlier)
108+
. Improved performance of stream_socket_client() and fsockopen() connects
109+
on Windows by avoiding a slow getsockopt(SO_ERROR) call on success
110+
(GH-24171). (vibbow)
108111

109112
- Standard:
110113
. Fixed bug #60110 (fclose(), file_put_contents(), copy() do not return false

‎main/network.c‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,13 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd,
412412
ret = -1;
413413
} else if (n == 0) {
414414
error = PHP_TIMEOUT_ERROR_VALUE;
415+
#ifdef PHP_WIN32
416+
} else if ((n & POLLOUT) && !(n & POLLPRI)) {
417+
/* Writable and not in exceptfds: the connect succeeded (see the
418+
* comment above). Skip getsockopt(SO_ERROR) here, as calling it
419+
* right after the connection completes can block for 10-25ms. */
420+
error = 0;
421+
#endif
415422
} else {
416423
len = sizeof(error);
417424
/* BSD-derived systems set errno correctly.

0 commit comments

Comments
 (0)