#21641 [Opn-Bgs]: stream_read() always passed count of 8192
ID: 21641 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] -Status: Open +Status: Bogus Bug Type: Filesystem function related Operating System: Linux 2.4.18 PHP Version: 4CVS-2003-01-14 (stable) New Comment: This is not a bug; PHP uses an internal read buffer 8192 bytes in length in order to be more efficient. You should note that fread() returns the correct number of bytes to your script. Previous Comments: [2003-01-14 14:59:09] [EMAIL PROTECTED] The stream_read() method of a class registered with stream_register_wrapper() is always passed 8192 as a count of bytes to read no matter what the second argument is to an fread() on that stream. This is reproduceable with the following class and test code: ?php class Stream_File { var $fn; var $fp; function stream_open($path, $mode, $options, $opened_path) { $url = parse_url($path); $this-fp = fopen($this-fn = $url['path'],$mode); return ($this-fp ? true : false); } function stream_close() { fclose($this-fp); } function stream_read($count) { error_log(stream_read: $count ); return fread($this-fp,$count); } function stream_write($data) { return fwrite($this-fp,$data); } function stream_eof() { return feof($this-fp); } function stream_tell() { return ftell($this-fp); } function stream_seek($offset,$whence) { return fseek($this-fp,$offset,$whence); } function stream_flush() { return fflush($this-fp); } } stream_register_wrapper('filetest', 'Stream_File') or die(Can't register filetest on Stream_File); $fp = fopen(filetest://localhost/tmp/hello,w+); fwrite($fp, testing\n); rewind($fp); $data = fread($fp, 10); echo $data\n; rewind($fp); $data = fread($fp,32000); echo $data\n; fclose($fp); ? Each time fread() is called on the stream, the error_log() call in stream_read() prints: stream_read: 8192 instead of stream_read: 10 or stream_read: 32000 -- Edit this bug report at http://bugs.php.net/?id=21641edit=1
#21641 [Opn-Bgs]: stream_read() always passed count of 8192
ID: 21641 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] -Status: Open +Status: Bogus Bug Type: Filesystem function related Operating System: Linux 2.4.18 PHP Version: 4CVS-2003-01-14 (stable) New Comment: Not a bug. Your stream should keep track of the maximum size available, and is responsible for keeping within range of the functions it calls. You already have a size and a position, you should be able to determine the maximum readable size using that information. If you don't want to see an error, you can use the @ operator. Previous Comments: [2003-01-14 15:20:44] [EMAIL PROTECTED] However, this causes problems for smaller values when the function that stream_read() is calling doesn't like it when the byte count is larger than its size. Consider this code (from the shared memory stream wrapper I am working on) function stream_read($count) { $data = shmop_read($this-shm,$this-pos,$count); $this-pos += strlen($data); return $data; } If the shared memory segment that $this-shm points to is less than 8192 bytes long, then shmop_read() complains that the count is out of range. Here's some sample code if you want to try (thanks to Xavier Noguer [[EMAIL PROTECTED]] who reported this to me): ?php class Stream_SHM { var $pos = 0; var $shm_key; var $size = 16384; // default size: 16k var $shm; function stream_open($path, $mode, $options, $opened_path) { $url = parse_url($path); $this-shm_key = $url['host']; if ((! intval($this-shm_key)) (! preg_match('/^0x[0-9a-f]+$/i', $this-shm_key))) { if ($options STREAM_REPORT_ERRORS) { trigger_error(Stream_SHM::stream_open: $this-shm_key is not a valid shm key.,E_USER_ERROR); } return false; } if (intval($url['port'])) { $this-size = intval($url['port']); } if (($mode != 'a') ($mode != 'c') ($mode != 'w') ($mode != 'n')) { if ($options STREAM_REPORT_ERRORS) { trigger_error(Stream_SHM::stream_open: $mode is not a valid mode (must be one of: a c n w),E_USER_ERROR); } return false; } if (! ($this-shm = shmop_open($this-shm_key,$mode,0600,$this-size))) { if ($options STREAM_REPORT_ERRORS) { trigger_error('Stream_SHM::stream_open: shmop_open() failed'); } return false; } $this-size = shmop_size($this-shm); return true; } function stream_close() { shmop_close($this-shm); } function stream_read($count) { $data = shmop_read($this-shm,$this-pos,$count); $this-pos += strlen($data); return $data; } function stream_write($data) { $count = shmop_write($this-shm,$data,$this-pos); $this-pos += $count; return $count; } function stream_eof() { return ($this-pos == ($this-size - 1)); } function stream_tell() { return $this-pos; } function stream_seek($offset,$whence) { switch ($whence) { case SEEK_SET: if (($offset = 0) ($offset $this-size)) { $this-pos = $offset; return true; } else { return false; } break; case SEEK_CUR: if (($offset = 0) (($this-pos + $offset) $this-size)) { $this-pos += $offset; return true; } else { return false; } break; case SEEK_END: if (($this-size + $offset) = 0) { $this-pos = $this-size + $offset; return true; } else { return false; } break; default: return false; } } function stream_flush() { return true; } } stream_register_wrapper('shm', 'Stream_SHM') or die(Can't register shm on Stream_SHM); echo \nUsing shm://0x:8192/\n; $mem = fopen(shm://0x:8192/,c); fwrite($mem, hola\n); rewind($mem); $data = fread($mem, 4); echo $data\n; fclose($mem); echo \nUsing shm://0x:8191/\n; $mem = fopen(shm://0x:8191/,c); fwrite($mem, hola\n); rewind($mem); $data = fread($mem, 4); echo $data\n; fclose($mem); echo \nUsing shmop_open() with size = 8191\n; //shm://0x:8191/; $mem = shmop_open(0x, c, 0600, 8191); $shm_bytes_written = shmop_write($mem, hola, 0); $data = shmop_read($mem, 0, 4); echo
#21641 [Opn-Bgs]: stream_read() always passed count of 8192
ID: 21641 Updated by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] -Status: Open +Status: Bogus Bug Type: Filesystem function related Operating System: Linux 2.4.18 PHP Version: 4CVS-2003-01-14 (stable) New Comment: function stream_read($count) { if ($count + $this-pos $this-size) { $count = $this-size - $this-pos; } $data = shmop_read($this-shm,$this-pos,$count); $this-pos += strlen($data); return $data; } Previous Comments: [2003-01-14 15:31:47] [EMAIL PROTECTED] I don't understand. In the shared memory example, how am I supposed to be able to read just four bytes from the stream? When I pass 4 to fread(), stream_open() gets 8192 $count. I can do the math just fine in stream_open() to trim that to 8191 (or whatever's left between the current position and the size of the segment), but that assumes that the fread() call was to read the rest of the segment. It's not. It's only for four bytes. [2003-01-14 15:25:57] [EMAIL PROTECTED] Not a bug. Your stream should keep track of the maximum size available, and is responsible for keeping within range of the functions it calls. You already have a size and a position, you should be able to determine the maximum readable size using that information. If you don't want to see an error, you can use the @ operator. [2003-01-14 15:20:44] [EMAIL PROTECTED] However, this causes problems for smaller values when the function that stream_read() is calling doesn't like it when the byte count is larger than its size. Consider this code (from the shared memory stream wrapper I am working on) function stream_read($count) { $data = shmop_read($this-shm,$this-pos,$count); $this-pos += strlen($data); return $data; } If the shared memory segment that $this-shm points to is less than 8192 bytes long, then shmop_read() complains that the count is out of range. Here's some sample code if you want to try (thanks to Xavier Noguer [[EMAIL PROTECTED]] who reported this to me): ?php class Stream_SHM { var $pos = 0; var $shm_key; var $size = 16384; // default size: 16k var $shm; function stream_open($path, $mode, $options, $opened_path) { $url = parse_url($path); $this-shm_key = $url['host']; if ((! intval($this-shm_key)) (! preg_match('/^0x[0-9a-f]+$/i', $this-shm_key))) { if ($options STREAM_REPORT_ERRORS) { trigger_error(Stream_SHM::stream_open: $this-shm_key is not a valid shm key.,E_USER_ERROR); } return false; } if (intval($url['port'])) { $this-size = intval($url['port']); } if (($mode != 'a') ($mode != 'c') ($mode != 'w') ($mode != 'n')) { if ($options STREAM_REPORT_ERRORS) { trigger_error(Stream_SHM::stream_open: $mode is not a valid mode (must be one of: a c n w),E_USER_ERROR); } return false; } if (! ($this-shm = shmop_open($this-shm_key,$mode,0600,$this-size))) { if ($options STREAM_REPORT_ERRORS) { trigger_error('Stream_SHM::stream_open: shmop_open() failed'); } return false; } $this-size = shmop_size($this-shm); return true; } function stream_close() { shmop_close($this-shm); } function stream_read($count) { $data = shmop_read($this-shm,$this-pos,$count); $this-pos += strlen($data); return $data; } function stream_write($data) { $count = shmop_write($this-shm,$data,$this-pos); $this-pos += $count; return $count; } function stream_eof() { return ($this-pos == ($this-size - 1)); } function stream_tell() { return $this-pos; } function stream_seek($offset,$whence) { switch ($whence) { case SEEK_SET: if (($offset = 0) ($offset $this-size)) { $this-pos = $offset; return true; } else { return false; } break; case SEEK_CUR: if (($offset = 0) (($this-pos + $offset) $this-size)) { $this-pos += $offset; return true; } else { return false; } break; case SEEK_END: if (($this-size + $offset) = 0) { $this-pos = $this-size + $offset; return true;