-
Notifications
You must be signed in to change notification settings - Fork 8k
Closed
Description
Description
Hi!
I have a PHP daemon with two forks. Each fork makes an HTTP requests to a remote server.
Sometimes(often) responses in forks are mixed up.
How to reproduce
Remote server
php -v
PHP 8.1.16 (cli) (built: Feb 14 2023 18:59:41) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.1.16, Copyright (c) Zend Technologies
server/index.php
<?php
switch ($_SERVER['REQUEST_URI']) {
case '/200':
http_response_code(200);
break;
case '/404':
http_response_code(404);
break;
default:
http_response_code(500);
}
symfony serve --no-tls --port=9999 --dir=server
[OK] Web server listening
The Web server is using PHP CGI 8.1.16
http://127.0.0.1:9999
[Web Server ] Feb 15 15:02:25 |DEBUG | PHP Reloading PHP versions
[Web Server ] Feb 15 15:02:25 |DEBUG | PHP Using PHP version 8.1.16 (from default version in $PATH)
[Web Server ] Feb 15 15:02:25 |INFO | PHP listening path="/usr/bin/php-cgi" php="8.1.16" port=11238
[Web Server ] Feb 15 15:02:28 |INFO | SERVER GET (200) /200 ip=""
[Web Server ] Feb 15 15:02:28 |INFO | SERVER GET (200) /200
[Web Server ] Feb 15 15:02:28 |WARN | SERVER GET (404) /404
[Web Server ] Feb 15 15:02:29 |INFO | SERVER GET (200) /200
[Web Server ] Feb 15 15:02:29 |WARN | SERVER GET (404) /404
[Web Server ] Feb 15 15:02:30 |WARN | SERVER GET (404) /404
[Web Server ] Feb 15 15:02:30 |INFO | SERVER GET (200) /200
[Web Server ] Feb 15 15:02:31 |WARN | SERVER GET (404) /404
[Web Server ] Feb 15 15:02:31 |INFO | SERVER GET (200) /200
curl 'http://{remote_server}:9999/200' -I
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
X-Powered-By: PHP/8.1.16
curl 'http://{remote_server}:9999/404' -I
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=UTF-8
X-Powered-By: PHP/8.1.16
Local server
php -v
PHP 8.1.0 (cli) (built: Dec 2 2021 12:37:35) (ZTS)
Copyright (c) The PHP Group
Zend Engine v4.1.0, Copyright (c) Zend Technologies
client/test.php
<?php
$url200 = 'http://{remote_server}:9999/200';
$url404 = 'http://{remote_server}:9999/404';
function request(\CurlMultiHandle $multi, string $url): int
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_multi_add_handle($multi, $ch);
do {
$status = curl_multi_exec($multi, $active);
if ($active) {
curl_multi_select($multi);
}
} while ($active && $status === CURLM_OK);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_multi_remove_handle($multi, $ch);
return (int)$httpCode;
}
$multi = curl_multi_init();
request($multi, $url200);// the request before pcntl_fork is important to reproduce error
$pid = pcntl_fork();
if ($pid === -1) {
exit(1);
}
if ($pid) {
$status = 0;
while (pcntl_wait($status, WNOHANG | WUNTRACED) === 0) {
$httpCode = request($multi, $url200);
if ($httpCode !== 200) {
printf("GET /200 - %d\n", $httpCode);
break;
}
sleep(1);
}
posix_kill($pid, SIGKILL);
} else {
while (true) {
$httpCode = request($multi, $url404);
if ($httpCode !== 404) {
printf("GET /404 - %d\n", $httpCode);
break;
}
sleep(1);
}
}
Resulted in this output:
GET /404 - 200
GET /200 - 0 //timeout
But I expected this output instead:
GET /404 - 404
GET /200 - 200
Error only reproduces with a remote(not local) server.
I tested it with two different remote servers.
PHP Version
8.1.0
Operating System
macOs BigSur 11.7.4