-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
run-tests.php
timeout doesn't work on Windows
#16889
Comments
Sad story: Lines 20 to 30 in f44eaac
and then: php-src/main/streams/plain_wrapper.c Lines 398 to 421 in f44eaac
So if there is nothing to read, we sleep for 32 seconds (in theory; likely way more in practice). Something enlightening for German speakers: https://learn.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select |
I may be wrong on the specifics but I do know those tests got stuck for way longer than 32 seconds. I ended up having to abort them after about half an hour or so. Very suboptimal either way lol |
With the default scheduler frequency on Windows (assuming usleep doesn't spin-wait; I didn't look at the impl) this could sleep for as long as 5000 seconds, or well over an hour. |
Yeah, that looks like what happens if no data is coming in. The code has been introduced by 0c98279, with some good reasoning (although still an excessive 18 sec wait in theory), and later got changed to what we have since 6f3dd4d. However, even drastically reducing this wait won't help in this case, since the timeout is on |
So I modified win32/select.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/win32/select.c b/win32/select.c
index f443325cf0..f404ae3982 100644
--- a/win32/select.c
+++ b/win32/select.c
@@ -135,7 +135,12 @@ PHPAPI int php_select(php_socket_t max_fd, fd_set *rfds, fd_set *wfds, fd_set *e
for (i = 0; i < n_handles; i++) {
if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
- FD_SET((uint32_t)handle_slot_to_fd[i], &aread);
+ DWORD avail_read = 0;
+ if (!PeekNamedPipe(handles[i], NULL, 0, NULL, &avail_read, NULL) || avail_read > 0) {
+ FD_SET((uint32_t)handle_slot_to_fd[i], &aread);
+ } else {
+ retcode--;
+ }
}
if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) {
FD_SET((uint32_t)handle_slot_to_fd[i], &awrite); The timeout works fine this way, but terminating the process won't work (so there are errors reported in the following), because we're going through the shell (cmd.exe) and killing this process, won't kill php.exe. I don't think there is any way to kill grandchild processes from PHP, and even doing this in C would be tedious (would need to enumerate all processes, and kill those with the given parent procid; not even sure what to do with grandchildren). The alternative would be to bypass the shell, but that will not work if there are redirects involved. |
Description
php-src/run-tests.php
Line 1187 in f44eaac
stream_select()
and pipes don't play nice together on Windows. It returns immediately & causes it to get stuck insidefread()
.Could use
socket
instead ofpipe
forstdout
andstderr
, (a la #5777), but this might break tests that usestream_select()
onSTDOUT
orSTDERR
.This was the real issue causing me trouble with #16849, as
run-tests.php
did not kill the test after the allotted time & the build hung forever.(Side note: This code looks dodgy too. What if only
stderr
has output? it's gonna block instdout
until something happens:php-src/run-tests.php
Lines 1200 to 1213 in f44eaac
PHP Version
8.1/8.2/8.3/8.4
Operating System
Windows
The text was updated successfully, but these errors were encountered: