diff --git a/ext/standard/tests/general_functions/proc_open_multiplex.phpt b/ext/standard/tests/general_functions/proc_open_multiplex.phpt new file mode 100644 index 0000000000000..704b0a50660e5 --- /dev/null +++ b/ext/standard/tests/general_functions/proc_open_multiplex.phpt @@ -0,0 +1,37 @@ +--TEST-- +Multiplexing of child output +--FILE-- + 0) { + foreach ($rset as $pipe) { + echo fread($pipe, 6), "\n"; + unset($read_pipes[array_search($pipe, $read_pipes)]); + } + $rset = $read_pipes; +} +?> +--EXPECT-- +hello9 +hello8 +hello7 +hello6 +hello5 +hello4 +hello3 +hello2 +hello1 +hello0 diff --git a/win32/select.c b/win32/select.c index 76d5ef1ee5be9..dec149b665ff5 100644 --- a/win32/select.c +++ b/win32/select.c @@ -16,12 +16,15 @@ #include "php.h" #include "php_network.h" +#include "win32/time.h" /* Win32 select() will only work with sockets, so we roll our own implementation here. * - If you supply only sockets, this simply passes through to winsock select(). * - If you supply file handles, there is no way to distinguish between * ready for read/write or OOB, so any set in which the handle is found will - * be marked as ready. Pipes will be checked if they are ready for read, though. + * be marked as ready. + * - If you supply only pipe handles in rfds, and no handles in wfds or efds, + * the pipes will only be marked as ready if there is data available. * - If you supply a mixture of handles and sockets, the system will interleave * calls between select() and WaitForMultipleObjects(). The time slicing may * cause this function call to take up to 100 ms longer than you specified. @@ -34,6 +37,7 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e HANDLE handles[MAXIMUM_WAIT_OBJECTS]; int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS]; int n_handles = 0, i; + int num_read_pipes = 0; fd_set sock_read, sock_write, sock_except; fd_set aread, awrite, aexcept; int sock_max_fd = -1; @@ -78,6 +82,9 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e sock_max_fd = i; } } else { + if (SAFE_FD_ISSET(i, rfds) && GetFileType(handles[n_handles]) == FILE_TYPE_PIPE) { + num_read_pipes++; + } handle_slot_to_fd[n_handles] = i; n_handles++; } @@ -136,7 +143,7 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) { if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) { DWORD avail_read = 0; - if (GetFileType(handles[i]) != FILE_TYPE_PIPE + if (num_read_pipes < n_handles || !PeekNamedPipe(handles[i], NULL, 0, NULL, &avail_read, NULL) || avail_read > 0 ) { @@ -156,6 +163,9 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e } } } + if (retcode == 0 && num_read_pipes == n_handles && sock_max_fd < 0) { + usleep(100); + } } while (retcode == 0 && (ms_total == INFINITE || GetTickCount64() < limit)); if (rfds) {