Commit de5a5820efb for php.net

commit de5a5820efbc98906f01cd9b8ff2759ab8c29172
Author: Calvin Buckley <calvinb@php.net>
Date:   Fri Jul 24 15:14:46 2026 -0300

    Use `php_pollfd_for_ms` more consistently for single fd polling (#22872)

    * ftp: For single fd poll calls, use php_pollfd_for_ms

    * pgsql: Use php_pollfd_for_ms in compat shim

    This is only used on pre-libpq 17.

    * fastcgi: Use php_pollfd_for_ms for single fd

    This also handles the case where poll isn't available (does that even
    matter nowadays?)

    * io: Use php_pollfd_for_ms for single fd poll

    * cli: Convert to php_pollfd_for from select

    This is not a poll call, but it is functionally the same as one; convert
    it to the single fd polling function which is clearer to read.

diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 0035e8508da..20a67950627 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -308,14 +308,9 @@ bool ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const cha

 				case SSL_ERROR_WANT_READ:
 				case SSL_ERROR_WANT_WRITE: {
-						php_pollfd p;
-						int i;
+						int i, events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;

-						p.fd = ftp->fd;
-						p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
-						p.revents = 0;
-
-						i = php_poll2(&p, 1, 300);
+						i = php_pollfd_for_ms(ftp->fd, events, 300);

 						retry = i > 0;
 					}
@@ -1388,14 +1383,9 @@ static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) {

 			case SSL_ERROR_WANT_READ:
 			case SSL_ERROR_WANT_CONNECT: {
-					php_pollfd p;
-					int i;
-
-					p.fd = fd;
-					p.events = POLLOUT;
-					p.revents = 0;
+					int i, events = POLLOUT;

-					i = php_poll2(&p, 1, 300);
+					i = php_pollfd_for_ms(fd, events, 300);

 					retry = i > 0;
 				}
@@ -1521,14 +1511,9 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)

 				case SSL_ERROR_WANT_READ:
 				case SSL_ERROR_WANT_CONNECT: {
-						php_pollfd p;
-						int i;
+						int i, events = POLLIN|POLLPRI;

-						p.fd = fd;
-						p.events = POLLIN|POLLPRI;
-						p.revents = 0;
-
-						i = php_poll2(&p, 1, 300);
+						i = php_pollfd_for_ms(fd, events, 300);

 						retry = i > 0;
 					}
@@ -1825,14 +1810,9 @@ static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp)

 				case SSL_ERROR_WANT_READ:
 				case SSL_ERROR_WANT_WRITE: {
-						php_pollfd p;
-						int i;
-
-						p.fd = data->fd;
-						p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
-						p.revents = 0;
+						int i, events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;

-						i = php_poll2(&p, 1, 300);
+						i = php_pollfd_for_ms(data->fd, events, 300);

 						retry = i > 0;
 					}
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index 87ccbe3424a..29ef4855a12 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -448,19 +448,14 @@ static int PQsocketPoll(int socket, int read, int write, time_t timeout)
 	if (!read && !write)
 		return 0;

-	php_pollfd fd;
-	int ts = -1;
-
-	fd.fd = socket;
-	fd.events = POLLERR;
-	fd.revents = 0;
+	int ts = -1, events = 0;

 	if (read) {
-		fd.events |= POLLIN;
+		events |= POLLIN;
 	}

 	if (write) {
-		fd.events |= POLLOUT;
+		events |= POLLOUT;
 	}

 	if (timeout != (time_t)ts) {
@@ -473,7 +468,7 @@ static int PQsocketPoll(int socket, int read, int write, time_t timeout)
 		}
 	}

-	return php_poll2(&fd, 1, ts);
+	return php_pollfd_for_ms(socket, events, ts);
 }
 #endif

diff --git a/main/fastcgi.c b/main/fastcgi.c
index 02ef614f463..abd55892803 100644
--- a/main/fastcgi.c
+++ b/main/fastcgi.c
@@ -68,15 +68,6 @@ static int is_impersonate = 0;
 # include <netdb.h>
 # include <signal.h>

-# if defined(HAVE_POLL_H) && defined(HAVE_POLL)
-#  include <poll.h>
-# elif defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
-#  include <sys/poll.h>
-# endif
-# if defined(HAVE_SYS_SELECT_H)
-#  include <sys/select.h>
-# endif
-
 #ifndef INADDR_NONE
 #define INADDR_NONE ((unsigned long) -1)
 #endif
@@ -1426,42 +1417,16 @@ int fcgi_accept_request(fcgi_request *req)
 				break;
 #else
 				if (req->fd >= 0) {
-#if defined(HAVE_POLL)
-					struct pollfd fds;
 					int ret;

-					fds.fd = req->fd;
-					fds.events = POLLIN;
-					fds.revents = 0;
 					do {
 						errno = 0;
-						ret = poll(&fds, 1, 5000);
+						ret = php_pollfd_for_ms(req->fd, POLLIN, 5000);
 					} while (ret < 0 && errno == EINTR);
-					if (ret > 0 && (fds.revents & POLLIN)) {
+					if (ret & POLLIN) {
 						break;
 					}
 					fcgi_close(req, 1, 0);
-#else
-					if (req->fd < FD_SETSIZE) {
-						struct timeval tv = {5,0};
-						fd_set set;
-						int ret;
-
-						FD_ZERO(&set);
-						FD_SET(req->fd, &set);
-						do {
-							errno = 0;
-							ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0;
-						} while (ret < 0 && errno == EINTR);
-						if (ret > 0 && FD_ISSET(req->fd, &set)) {
-							break;
-						}
-						fcgi_close(req, 1, 0);
-					} else {
-						fcgi_log(FCGI_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
-						fcgi_close(req, 1, 0);
-					}
-#endif
 				}
 #endif
 			}
diff --git a/main/io/php_io.c b/main/io/php_io.c
index bd45ec88879..6954cd4bfde 100644
--- a/main/io/php_io.c
+++ b/main/io/php_io.c
@@ -23,7 +23,6 @@
 #include <winsock2.h>
 #else
 #include <unistd.h>
-#include <poll.h>
 #endif

 static php_io php_io_instance = {
@@ -106,13 +105,9 @@ static int php_io_generic_wait_for_data(php_io_fd *fd)
 		? -1
 		: (int) (fd->timeout.tv_sec * 1000 + fd->timeout.tv_usec / 1000);

-	struct pollfd pfd;
-	pfd.fd = fd->fd;
-	pfd.events = POLLIN;
-
 	int ret;
 	do {
-		ret = poll(&pfd, 1, timeout_ms);
+		ret = php_pollfd_for_ms(fd->fd, POLLIN, timeout_ms);
 	} while (ret == -1 && errno == EINTR);

 	return ret;
diff --git a/main/io/php_io_copy_linux.c b/main/io/php_io_copy_linux.c
index 9a1810349d3..af92b14a64d 100644
--- a/main/io/php_io_copy_linux.c
+++ b/main/io/php_io_copy_linux.c
@@ -54,13 +54,9 @@ static inline int php_io_linux_wait_for_data(php_io_fd *fd)
 		timeout_ms = ptimeout->tv_sec * 1000 + ptimeout->tv_usec / 1000;
 	}

-	struct pollfd pfd;
-	pfd.fd = fd->fd;
-	pfd.events = POLLIN;
-
 	int ret;
 	do {
-		ret = poll(&pfd, 1, timeout_ms);
+		ret = php_pollfd_for_ms(fd->fd, POLLIN, timeout_ms);
 	} while (ret == -1 && errno == EINTR);

 	return ret;
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index e5e573d1533..9095fb10dd4 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -78,12 +78,6 @@
 #include "php_cli_process_title.h"
 #include "php_cli_process_title_arginfo.h"

-#ifndef PHP_WIN32
-# define php_select(m, r, w, e, t)	select(m, r, w, e, t)
-#else
-# include "win32/select.h"
-#endif
-
 #if defined(PHP_WIN32) && defined(HAVE_OPENSSL_EXT)
 # include "openssl/applink.c"
 #endif
@@ -218,20 +212,12 @@ static void print_extensions(void) /* {{{ */
 #ifdef PHP_WRITE_STDOUT
 static inline bool sapi_cli_select(php_socket_t fd)
 {
-	fd_set wfd;
 	struct timeval tv;
-	int ret;
-
-	FD_ZERO(&wfd);
-
-	PHP_SAFE_FD_SET(fd, &wfd);

 	tv.tv_sec = (long)FG(default_socket_timeout);
 	tv.tv_usec = 0;

-	ret = php_select(fd+1, NULL, &wfd, NULL, &tv);
-
-	return ret != -1;
+	return php_pollfd_for(fd, POLLOUT, &tv) != -1;
 }
 #endif