Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:10293 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 53913 invoked by uid 1010); 7 Jun 2004 14:07:10 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 53755 invoked from network); 7 Jun 2004 14:07:08 -0000 Received: from unknown (HELO mail.zend.com) (192.117.235.230) by pb1.pair.com with SMTP; 7 Jun 2004 14:07:08 -0000 Received: (qmail 7503 invoked from network); 7 Jun 2004 14:07:06 -0000 Received: from int.zend.com (HELO AndiNotebook.zend.com) (10.1.1.1) by int.zend.com with SMTP; 7 Jun 2004 14:07:06 -0000 Message-ID: <5.1.0.14.2.20040607170659.01f2fc08@127.0.0.1> X-Sender: andi@127.0.0.1 X-Mailer: QUALCOMM Windows Eudora Version 5.1 Date: Mon, 07 Jun 2004 17:07:06 +0300 To: "Alexander Valyalkin" ,internals@lists.php.net In-Reply-To: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; format=flowed Subject: Re: [PHP-DEV] readfile() improvements From: andi@zend.com (Andi Gutmans) References: Can you send a unified diff? At 02:08 PM 6/7/2004 +0300, Alexander Valyalkin wrote: >When I try to print huge files (greate than 500Mb) using readfile() >function, my computer crashes. >Why? I found in the PHP 4.3.7 sources the file /main/strems.c and function >_php_stream_passthru() in it. The readfile() uses this function to print >content of the file. >Below you can see source of the function with my comments: >=================================================================== >PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC >TSRMLS_DC) >{ > size_t bcount = 0; > int ready = 0; > char buf[8192]; >#ifdef HAVE_MMAP > int fd; >#endif > >#ifdef HAVE_MMAP > if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET) > && stream->filterhead == NULL > && php_stream_tell(stream) == 0 > && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, >(void*)&fd, 0)) > { > struct stat sbuf; > off_t off; /* !!! offset == 0 (see above condition >[php_stream_tell(stream) == 0] ) */ > void *p; > size_t len; > > fstat(fd, &sbuf); /* !!! there is no error check after this line */ > > if (sbuf.st_size > sizeof(buf)) { > off = php_stream_tell(stream); /* !!! offset == 0 (see above) >*/ > len = sbuf.st_size - off; > /* suppose len > 1 Gb, machine has 128Mb RAM and 128Mb swap. >What happens after the next line? */ > p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off); /* !!! why >MAP_SHARED, not MAP_PRIVATE ? > First parameter of the mmap is (void *) type, >not (int) */ > if (p != (void *) MAP_FAILED) { > BG(mmap_file) = p; /* !!! what sense of this and next >string? Thread safety? > I don't understand how it works here */ > BG(mmap_len) = len; > PHPWRITE(p, len); > BG(mmap_file) = NULL; /* !!! thread safety? ok. why there >is not BG(mmap_len) = 0 on the next line ? */ > munmap(p, len); /* !!! missing error check after munmap */ > bcount += len; > ready = 1; > } > } > } >#endif > if(!ready) { > int b; > > while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) { > PHPWRITE(buf, b); > bcount += b; > } > } > return bcount; >} >=================================================================== > >And here you can see my version of the function: > >=================================================================== >PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC >TSRMLS_DC) >{ > size_t bcount = 0; /* counter of printed out bytes */ > int is_mapped = 0; > char buf[8192]; > size_t buf_len = sizeof(buf); >#ifdef HAVE_MMAP > int fd; > > if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET) > && stream->filterhead == NULL > && php_stream_tell(stream) == 0 > && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, >(void*)&fd, 0)) > { > is_mapped = 1; > buf_len = 1024 * 1024; /* default length of the mapped memory */ > struct stat sbuf; > void *p; /* pinter to the mapped part of file */ > size_t len; > /* get the length of local file connected to descriptor fd */ > fstat(fd, &sbuf); > if (errno) { > /* cannot get length of file */ > php_error_docref(NULL TSRMLS_CC, E_ERROR, "cannot get length >of the file"); > return bcount; > } > len = (size_t) sbuf.st_size; > /* print to the output buffer file contents */ > while (bcount < len) { > if (len - bcount < buf_len) buf_len = len - bcount; > p = mmap(NULL, buf_len, PROT_READ, MAP_PRIVATE, fd, (off_t) >bcount); /* try to map part of the file to memory */ > if (p == (void *) MAP_FAILED) { > /* error when mapping part of the file to memory */ > php_error_docref(NULL TSRMLS_CC, E_ERROR, "mmap error: >cannot map part of the file to memory"); > break; > } > PHPWRITE(p, buf_len); > munmap(p, buf_len); /* try to unmap allocated memory */ > if (errno) { > /* error when unmapping memory */ > php_error_docref(NULL TSRMLS_CC, E_ERROR, "mmap error: >cannot unmap allocated memory"); > break; > } > bcount += buf_len; > } > } >#endif > if (!is_mapped) { > /* print to the output buffer stream contents */ > while ((buf_len = php_stream_read(stream, buf, sizeof(buf))) > 0) { > PHPWRITE(buf, buf_len); > bcount += buf_len; > } > } > return bcount; >} > > >-- >Using Opera's revolutionary e-mail client: http://www.opera.com/m2/ > >-- >PHP Internals - PHP Runtime Development Mailing List >To unsubscribe, visit: http://www.php.net/unsub.php