From 45baf072c4a11e182022b0db14bdacf171032321 Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 5 Nov 2026 17:58:22 +0500 Subject: [PATCH] Fix GH-25204: False EOF on an idle pipe on Windows --- main/streams/plain_wrapper.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index b6c117c52e20..d3791b60f6a2 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -433,12 +433,14 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count) HANDLE ph = (HANDLE)_get_osfhandle(data->fd); int retry = 0; DWORD avail_read = 0; + BOOL peeked; do { /* Look ahead to get the available data amount to read. Do the same as read() does, however not blocking forever. In case it failed, no data will be read (better than block). */ - if (!PeekNamedPipe(ph, NULL, 0, NULL, &avail_read, NULL)) { + peeked = PeekNamedPipe(ph, NULL, 0, NULL, &avail_read, NULL); + if (!peeked) { break; } /* If there's nothing to read, wait in 10us periods. */ @@ -447,6 +449,11 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count) } } while (0 == avail_read && retry++ < 3200000); + /* The wait ran out on an open pipe, this is not the end of the stream. */ + if (peeked && 0 == avail_read) { + return 0; + } + /* Reduce the required data amount to what is available, otherwise read() will block.*/ if (avail_read < count) {