Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:60393 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 81579 invoked from network); 1 May 2012 14:57:58 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 May 2012 14:57:58 -0000 Authentication-Results: pb1.pair.com smtp.mail=rasmus@lerdorf.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=rasmus@lerdorf.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain lerdorf.com from 209.85.220.170 cause and error) X-PHP-List-Original-Sender: rasmus@lerdorf.com X-Host-Fingerprint: 209.85.220.170 mail-vx0-f170.google.com Received: from [209.85.220.170] ([209.85.220.170:46696] helo=mail-vx0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 6C/96-38165-4F9FF9F4 for ; Tue, 01 May 2012 10:57:57 -0400 Received: by vcbfo14 with SMTP id fo14so3171936vcb.29 for ; Tue, 01 May 2012 07:57:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:x-enigmail-version:content-type :content-transfer-encoding:x-gm-message-state; bh=u7TTZTaEXfoAUziFurN+AzUWDPM5hpCHaxihGR9lzig=; b=jTfmtCwsmcvlo1i/t8rdI3iIxuNJwF9WKX1dt6a/3mgUlLHJm5qDLsfRd+iv043UUU p97x0AUiK/nUkeIjTzsvvesVgw7BlcHSANhn+BAY7HIN4PtLL1c4khTY9dFyptmObPsm dDegWXnv4mfW3O5pRGXOsVPtdyw1CeY2WRYIkuw0cRy2Y4wyx0C6E6i6KQNnRCqfLEDr Nm1n37tgw3INo4NqQyC1sIkOHtjXdLic5brLB0bVolLtaUU13CZMDQf8iNxPuT2B8nfb 8iSXnBAqUkUpoonhKCEN67PwYU2Vd+1FIvJVzRadiJFHjMrXF8JH+qJrgFqiOt1ivqdL w32A== Received: by 10.52.73.132 with SMTP id l4mr21496724vdv.4.1335884273972; Tue, 01 May 2012 07:57:53 -0700 (PDT) Received: from [192.168.200.5] (c-50-131-44-225.hsd1.ca.comcast.net. [50.131.44.225]) by mx.google.com with ESMTPS id iz3sm32485862vdb.11.2012.05.01.07.57.52 (version=SSLv3 cipher=OTHER); Tue, 01 May 2012 07:57:53 -0700 (PDT) Message-ID: <4F9FF9EF.4040107@lerdorf.com> Date: Tue, 01 May 2012 07:57:51 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120410 Thunderbird/11.0.1 MIME-Version: 1.0 To: Paul Reinheimer CC: internals@lists.php.net, Larry Garfield References: <4F9E2173.50005@garfieldtech.com> <000e01cd269a$06f15230$14d3f690$@php.net> <002701cd26b5$1cd0bb70$56723250$@thetaphi.de> <4F9EC8B4.3040600@garfieldtech.com> <4F9F4208.7020106@garfieldtech.com> <4F9FF2B9.7060301@lerdorf.com> In-Reply-To: <4F9FF2B9.7060301@lerdorf.com> X-Enigmail-Version: 1.4 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Gm-Message-State: ALoCoQlYdXQAhN8H4Ty5ZNccGpyJi2vk1tJfV/RgC+tYTwUEAv11klpu95ofhSwkoFYSrGF2csSj Subject: Re: [PHP-DEV] readfile() memory usage From: rasmus@lerdorf.com (Rasmus Lerdorf) On 05/01/2012 07:27 AM, Rasmus Lerdorf wrote: > On 05/01/2012 06:39 AM, Paul Reinheimer wrote: >> Hi Larry, >> >>> Fascinating. I even verified the md5sum of the file I got on the other end >>> just to be sure. I'll hold off on the blog post then. :-) I look forward >>> to your test setup. >> >> The server in question is still on PHP 5.2.13 >> >> Script: >> > ini_set('memory_limit', '8M'); >> $name = uniqid() . ".zip"; >> header('Content-type: application/zip'); >> header("Content-Disposition: attachment; filename=\"$name\""); >> readfile('../../filestorage/4f9e9e3b9bcff.zip'); >> >> File Information: >> [user@host public]$ ls -alh ../../filestorage/4f9e9e3b9bcff.zip >> -rw-r--r-- 1 apache apache 27M Apr 30 10:14 ../../filestorage/4f9e9e3b9bcff.zip >> >> Error: >> [Tue May 01 09:30:48 2012] [error] [client 198.136.162.2] PHP Fatal >> error: Allowed memory size of 8388608 bytes exhausted (tried to >> allocate 27617281 bytes) in >> /home/lots/of/path.org/stuff/public/rf822.php on line 6 >> >> >> I'll try something newer, but I wanted to prove myself not crazy and >> do it on the server in question first. > > That's odd, because PHP 5.2 has identical code in this respect. Wez > committed these changes in 2002: > > https://github.com/php/php-src/commit/a662f012bba5a6fdc50533673f3fff47bf9af219#diff-5 > > So it has been like this for quite a while. Does that server have > implicit unlimited output buffering turned on in your ini file? And actually, that patch just made it use streams. Even before the internal streams API the function worked the same way. In PHP 4.2 it used php_passthru_fd which looked like this: https://github.com/php/php-src/blob/PHP-4.2.0/ext/standard/file.c#L1526 Sascha added the mmap implementation we still use today in 1999: https://github.com/php/php-src/commit/dda0b783df7d849df01fa831febbc1e34b5b8dd3 But even prior to that readfile would still buffer in 8k chunks. The PHP 2.0.1 implementation (very scary to look at code I wrote 17 or 18 years ago): /* * Read a file and write the ouput to stdout */ void ReadFile(void) { Stack *s; char buf[8192],temp[8]; FILE *fp; int b,i, size; s = Pop(); if(!s) { Error("Stack error in ReadFile"); return; } if(!*(s->strval)) { Push("-1",LNUMBER); return; } #if DEBUG Debug("Opening [%s]\n",s->strval); #endif StripSlashes(s->strval); #if PHP_SAFE_MODE if(!CheckUid(s->strval,1)) { Error("SAFE MODE Restriction in effect. Invalid owner of file to be read."); Push("-1",LNUMBER); return; } #endif fp = fopen(s->strval,"r"); if(!fp) { Error("ReadFile(\"%s\") - %s",s->strval,strerror(errno)); Push("-1",LNUMBER); return; } size= 0; php_header(0,NULL); while((b = fread(buf, 1, sizeof(buf), fp)) > 0) { for(i = 0; i < b; i++) PUTC(buf [i]); size += b ; } fclose(fp); sprintf(temp,"%d",size); Push(temp,LNUMBER); } -Rasmus