[php-src] Issue #10633: curl responses mixed up with pcnt_fork
| From: | mrsuh | Date: | Mon, 20 Feb 2023 10:29:30 +0000 |
| Subject: | [php-src] Issue #10633: curl responses mixed up with pcnt_fork | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-243754@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/10633
Author: mrsuh
### 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
```bash
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
<?php
switch ($_SERVER['REQUEST_URI']) {
case '/200':
http_response_code(200);
break;
case '/404':
http_response_code(404);
break;
default:
http_response_code(500);
}
```
```bash
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
```
```bash
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
```bash
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:
```bash
GET /404 - 200
GET /200 - 0 //timeout
```
But I expected this output instead:
```bash
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