From: magical...@php.net Operating system: Linux Gentoo 2.6.32 PHP version: 5.3.1 PHP Bug Type: Streams related Bug description: fread() on blocking stream will block even if data is available
Description: ------------ On a blocking stream, a call to fread() will return even if the passed buffer size has not been reached. A call to fread() should return immediatly if there is data pending to be read (buffered by php). Instead of that, php will call poll() on the stream to wait for more data to arrive, then will return the previously read data and the new data. Suggestion: if fread() is called on a blocking stream that already contains data, PHP should call poll() with a 0 timeout, read any newly available data and return immediatly. If no data is currently in PHP's internal buffer, current behaviour can be kept. (it is also possible to skip completly the poll() part and directly return any pending data without checking if the real stream has anything, but I believe that it might not be as logical, a call to fread() should read) Reproduce code: --------------- <?php echo 'Testing PHP version: '.phpversion()."\n"; $pair = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); $pid = pcntl_fork(); if ($pid == -1) die("Failed to fork\n"); if ($pid > 0) { // parent fclose($pair[0]); while(!feof($pair[1])) { $start = microtime(true); $data = fread($pair[1], 256); printf("fread took %01.2fms to read %d bytes\n", (microtime(true)-$start)*1000, strlen($data)); } exit; } // child fclose($pair[1]); while(!feof($pair[0])) { fwrite($pair[0], "Hello 1\n"); // 8 bytes usleep(5000); fwrite($pair[0], str_repeat('a', 300)."\n"); // 301 bytes sleep(1); } Expected result: ---------------- Testing PHP version: 5.3.1 fread took 0.09ms to read 8 bytes fread took 5.08ms to read 256 bytes fread took 0.00ms to read 45 bytes fread took 1000.10ms to read 8 bytes fread took 5.04ms to read 256 bytes fread took 0.00ms to read 45 bytes fread took 1000.10ms to read 8 bytes fread took 5.04ms to read 256 bytes (etc) Actual result: -------------- Testing PHP version: 5.3.1 fread took 0.09ms to read 8 bytes fread took 5.08ms to read 256 bytes fread took 1000.10ms to read 53 bytes fread took 5.04ms to read 256 bytes fread took 1000.10ms to read 53 bytes fread took 5.04ms to read 256 bytes (etc) -- Edit bug report at http://bugs.php.net/?id=51056&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=51056&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=51056&r=trysnapshot53 Try a snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=51056&r=trysnapshot60 Fixed in SVN: http://bugs.php.net/fix.php?id=51056&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=51056&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=51056&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=51056&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=51056&r=needscript Try newer version: http://bugs.php.net/fix.php?id=51056&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=51056&r=support Expected behavior: http://bugs.php.net/fix.php?id=51056&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=51056&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=51056&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=51056&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=51056&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=51056&r=dst IIS Stability: http://bugs.php.net/fix.php?id=51056&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=51056&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=51056&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=51056&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=51056&r=mysqlcfg