php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #50111 memory not properly freed when stream_context_create is used (PHP_5_2 only!)
Submitted: 2009-11-07 09:26 UTC Modified: 2009-11-19 15:45 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: datibbaw@php.net Assigned:
Status: Wont fix Package: Streams related
PHP Version: 5.2.11 OS: Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: datibbaw@php.net
New email:
PHP Version: OS:

 

 [2009-11-07 09:26 UTC] datibbaw@php.net
Description:
------------
When stream_context_create() is used in conjunction with file_get_contents() or other stream related functions that accept a context parameter, memory is being leaked.

Reproduce code:
---------------
for ($i=0;$i<5;++$i){
  $m0 = memory_get_usage();
  file_get_contents('http://www.google.com', false, stream_context_create(array()));
  $m1 = memory_get_usage();
  echo $m1-$m0,PHP_EOL;
}

Expected result:
----------------
X (where X is the memory increase for the first iterator)
0
0
0
0


Actual result:
--------------
X (where X is the memory increase for the first iterator)
384 (or something similar)
420
420
480

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-11-08 01:06 UTC] datibbaw@php.net
Code to reproduce can be made simpler, since the problem seems to be with stream_context_create():

$m0 = $m1 = $i = 0;
$c = null;
while ($i<5) {
    $m0 = memory_get_usage();
    $c = stream_context_create();
    $m1 = memory_get_usage();
    echo $m1-$m0,PHP_EOL;
    ++$i;
}
 [2009-11-08 21:17 UTC] srinatar@php.net
hmmm.. not sure, why u think there is a leak.

when u write this below code
$c = stream_context_create();

u do understand that underlying php engine need to do some processing  
underneath and store the reference of this processing in $c variable. 
this does require some memory consumption. 

i guess, if u do some thing like and still no
$c = stream_context_create..
unset($c);
$m1 = memory_get_usage();

and still see memory leak , then let us know..
 [2009-11-08 23:27 UTC] datibbaw@php.net
Test code changed to (added the unset() statement):

$m0 = $m1 = $i = 0;
$c = null;
while ($i<5) {
    $m0 = memory_get_usage();
    $c = stream_context_create();
    unset($c);
    $m1 = memory_get_usage();
    echo $m1-$m0,PHP_EOL;
    ++$i;
}

Output:
336
420
420
420
420

Though, as a language feature I would assume that in the second iteration the memory occupied by the previous assignment would be freed implicitly. Is that a wrong assumption?
 [2009-11-09 17:11 UTC] jani@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php


 [2009-11-18 14:05 UTC] datibbaw@php.net
I've change the summary a bit to avoid confusion with an actual memory leak (those that would get reported by php at the end of execution in debug mode).

When kept running (using cli), an endless loop of given code would eventually result in an out-of-memory error.

In PHP 5.3.x this no longer happens, so it seems that this has been rectified before, just not in this branch. It would be nice if the same fix could be applied here.
 [2009-11-18 18:14 UTC] jani@php.net
What code? There is no such script in this report that crashes. Not even when changed to loop thousands of times. Not with PHP_5_2 or PHP_5_3 or HEAD branches. So please, come up with a proper reproducing script.
 [2009-11-18 22:03 UTC] datibbaw@php.net
<?php

echo "This is PHP ", phpversion(),PHP_EOL;
ini_set("memory_limit", "0");

for ($i=0;$i<2000;++$i) {
  $x = stream_context_create(array());
  unset($x);
}
echo "Done", PHP_EOL;

?>
----------------
$ /usr/local/php-5.1.0/bin/php lala.php
This is PHP 5.1.0
Done
----------------
$ /usr/local/php-5.1.1/bin/php lala.php
This is PHP 5.1.1
Done
----------------
$ /usr/local/php-5.1.2/bin/php lala.php
This is PHP 5.1.2
Done
----------------
$ /usr/local/php-5.2.9/bin/php lala.php
This is PHP 5.2.9

Fatal error: Allowed memory size of 262144 bytes exhausted at /usr/local/src/php-5.2.9/Zend/zend_list.c:47 (tried to allocate 12 bytes) in /home/tjerk/lala.php on line 7
----------------
$ /usr/local/php-5.2.11/bin/php lala.php
This is PHP 5.2.11

Fatal error: Allowed memory size of 262144 bytes exhausted at /usr/local/src/php-5.2.11/main/streams/streams.c:1945 (tried to allocate 16 bytes) in /home/tjerk/lala.php on line 7
----------------
$ /usr/local/php-5.3/bin/php lala.php
This is PHP 5.3.0RC3-dev
Done
 [2009-11-19 09:38 UTC] jani@php.net
To disable memory_limit, you need to set it to -1, not 0.
 [2009-11-19 13:39 UTC] datibbaw@php.net
I'm not trying to disable memory_limit. Setting it to "0" just happens to make the issue appear faster.

Changing it to the below value of 1k yields the same results as mentioned earlier, tested on the same 5 php configurations:

ini_set("memory_limit", "1000");

 [2009-11-19 15:28 UTC] datibbaw@php.net
My results for PHP 5.1.x were wrong, because I didn't compile them with --enable-memory-limit, so the ini_set() wasn't actually working for those; guess it was automatically added in 5.2.x even in the presence of --disable-all ... my bad =(

After some more research on the PHP code itself, the problem seems to lie in the fact that the following two functions are called by stream_context_create():
zend_list_insert() - called by php_stream_context_alloc()
zend_list_addref() - called by php_stream_context_to_zval()

This results in a refcount of 2 for each context returned. This has changed in 5.3.x but not sure in how many places ;-)
 [2009-11-19 15:45 UTC] jani@php.net
PHP 5.3 has better garbage collection, hence this works there and not in 5.2, wont fix for 5.2.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC