[php-src] Issue #9994: stream_copy_to_stream() returns on socket timeout

From: Date: Wed, 23 Nov 2022 17:44:38 +0000
Subject: [php-src] Issue #9994: stream_copy_to_stream() returns on socket timeout
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-242891@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/9994 Author: negram ### Description The code is a little big huge, so let me explain first. If the source socket was created as blocking, stream_copy_to_stream returns as soon as default_socket_timeout is reached, before the actual EOF happened. That's probably the expected behaviour but we couldn't find this in the documentation, maybe that should be improved. The behaviour changed recently if the source socket was created from stream_socket_accept on a non-blocking socket on Linux (it looks related to #8472, #9252). The following code: ```php <?php const SEND_BYTES = 10 * 1024; if (pcntl_fork() == 0) { doSender(); } doServer(); pcntl_wait($status); // wait for the sender process function doSender() { $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_connect($socket, '127.0.0.1', 9638); $string = str_repeat("0", SEND_BYTES); $written = 0; for ($i = 0; $i < 2; ++ $i) { $bytes = socket_write($socket, $string . "\n"); assert($bytes !== false, "server died"); $written += $bytes; sleep((int)ini_get('default_socket_timeout') * 2); } printf("written: %d\n", $written); exit; } function doServer() { $server = new Server; $server->doServer(); } class Server { private $socket_server; function doServer() { $this->socket_server = $this->startSocketServer(); while (true) { //stream_socket_accept emits a warning if interrupted by a signal if (@$client = stream_socket_accept($this->socket_server, 0)) { $this->handleClient($client); break; } usleep(10000); //0.01 sec } fclose($this->socket_server); } function startSocketServer() { $socket_server = stream_socket_server("tcp://0.0.0.0:9638", $errno, $errstr); assert(!empty($socket_server), "Could not start socket server [$errno]: $errstr"); if (!stream_set_blocking($socket_server, false)) { assert(false, "Could not set socket server to non-blocking mode"); } return $socket_server; } protected function handleClient($client) { $handle = fopen("/dev/null", 'w'); assert(!empty($handle), "Could not open client output stream for write"); $bytes_copied = stream_copy_to_stream($client, $handle); printf("read %d bytes\n", $bytes_copied); fclose($handle); fclose($client); } } ``` Resulted in this output: ``` $ php -ddefault_socket_timeout=2 socket-test.php read 10241 bytes written: 20482 ``` But I expected this output instead PHP 8.0.22 returned: ``` $ php -ddefault_socket_timeout=2 socket-test.php written: 20482 Read 20482 bytes ``` ### PHP Version PHP 8.0.25 ### Operating System CentOS Stream 8

« previous php.bugs (#242891) next »