ID:               45161
 User updated by:  humbads at alum dot mit dot edu
 Reported By:      humbads at alum dot mit dot edu
 Status:           Open
 Bug Type:         cURL related
 Operating System: FreeBSD 6.2, Windows XP SP3
 PHP Version:      5.2.6
 New Comment:

I did some more investigation, and found that this is not really a leak
as much as it is runaway memory usage.  PHP does indeed free the memory
eventually.

The problem is in interface.c curl_setopt under CURLOPT_URL.   The
function is making a copy of the string parameter, in this case, the
URL, and saving that to the "to_free" list.  That list is not freed
until sometime later, so repeatedly setting CURLOPT_URL on the same
handle will keep using more memory.  In the sample code I posted, the
memory only increases during the curl_setopt CURLOPT_URL function call.

This is just an inefficient design of the PHP curl handle.  One way
around it is for the code to maintain only one copied string for each
CURLOPT string option.  If the same CURLOPT string option is set again,
it should free the previously created string, and create a new one.

At the PHP level, the only workaround for now is to periodically close
the handle and then create a new one with curl_init.  This seems to cap
the memory usage.


Previous Comments:
------------------------------------------------------------------------

[2008-06-03 16:07:04] humbads at alum dot mit dot edu

Below is the r.php script.  When testing this bug report, please use
this script (or some other URL) so my poor server does not get
hammered.

<?php
// This script runs a variable amount of time
// and generates a variable amount of data

// Output a random number of blank space
$s = microtime(true);
$m = rand(100,200);
$bytes = 0;
for($i = 0; $i < $m; $i++) {
        $message = "         \n";
        print $message;
        $bytes += strlen($message);
        usleep(10);
}

// Print time taken and the value of the "echo" parameter
print isset($_REQUEST['echo']) ? 'echo: '.$_REQUEST['echo'].' ' : "";
print $bytes.' bytes ';
print " in ";
print round(microtime(true) - $s, 4)." seconds";
exit();
?>

------------------------------------------------------------------------

[2008-06-03 15:04:41] humbads at alum dot mit dot edu

Description:
------------
Reusing a curl handle for multiple requests leaks memory.  It leaks
about 100 bytes per request.  This is a problem when making a large
number of requests using the same handle.  Libcurl documentation says to
always reuse the handle when possible in order to reuse connections. 
The bug occurs on Windows XP/IIS and Apache/FreeBSD 6.2.

Reproduce code:
---------------
<?php
// Reuse curl handle memory leak test
$ch = curl_init();
$startmem = memory_get_usage();
for($i = 0; $i < 100; $i++) {
  $fp = fopen('/dev/null', "w");
  curl_setopt($ch, CURLOPT_URL,
    'http://debug.atensoftware.com/r.php?echo='.rand());
  curl_setopt($ch, CURLOPT_FILE, $fp);
  curl_exec($ch);

  fclose($fp);
  unset($fp);
  print "$i-mem: ".(memory_get_usage() - $startmem)." bytes\n";
}

?>

Expected result:
----------------
The memory usage should not increase after each request.



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=45161&edit=1

Reply via email to