ID: 39037 User updated by: eugen at id dot com dot ua Reported By: eugen at id dot com dot ua -Status: Closed +Status: Open Bug Type: cURL related Operating System: Fedora Core 5 PHP Version: 5.1.6 New Comment:
In php5.2 2006-10-06 06:30 snapshot problem is not solved. Even this code, where each handle is destroyed after use doesn't release memory: <?php $tasks = array("http://www.google.com","http://www.php.net"); $mh = curl_multi_init(); reset($tasks); while (list($index, $row)=each($tasks)) { $cid = curl_init($row); curl_setopt($cid, CURLOPT_RETURNTRANSFER, 1); curl_multi_add_handle($mh, $cid); unset($cid); // unset curl handle } do { $n = curl_multi_exec($mh, $active); $info = curl_multi_info_read($mh); if (!empty($info)) { $memory_usage = memory_get_usage(); // this should free up resources curl_close($info['handle']); $diff = memory_get_usage() - $memory_usage; echo "Memory usage was: $memory_usage, after curl_close: $diff bytes more\n"; } unset($info); } while ($active); ?> > Meanwhile lets look into your code ... Does it matter how much refs for curl connection I have? Lets look at curl_close documentation (http://ua2.php.net/manual/en/function.curl-close.php): This function closes a CURL session and (!!!)frees all resources(!!!). There's nothing abount refcounts. P.S. In submitted script curl releases memory when after while loop is finished I call curl_multi_init() again. %| Previous Comments: ------------------------------------------------------------------------ [2006-10-05 15:37:39] [EMAIL PROTECTED] I've commited a small patche which decreases refcount for curl handles added to the multi handle (previously they were destroyed on shutdown). The patch will appear in the next snapshot. Thanks you for your help. Meanwhile lets look into your code: $curl_handles[ $index ] = $cid; // refcount++ ... if ($handle == $info['handle']) { // refcount++ ... curl_close($info['handle']); // refcount-- 1 + 1 - 1 = 1, so curl_close() doesn't actually destroy the handle, but just reduces its refcount. To destroy the handles you need to unset() numerous arrays they were added to. ..Or you can put this code into a function, this way all variables will be destroyed automatically when execution goes out of the scope. Also, notice that curl_close() IS NOT called for the last handle, because $active is false at the moment. ------------------------------------------------------------------------ [2006-10-05 08:22:23] eugen at id dot com dot ua I think curl_close() MUST release memory. And it does when using curl_exec() like this: <?php $ch = curl_init(); // set URL and other appropriate options curl_setopt($ch, CURLOPT_URL, "http://www.php.net/"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // grab URL and pass it to the browser curl_exec($ch); $memory_usage = memory_get_usage(); // close curl resource, and free up system resources curl_close($ch); echo "Memory usage was: $memory_usage, after curl_close - ".(memory_get_usage() - $memory_usage)." bytes more\n"; ?> In this code curl_close() releases used memory. But when I use it with curl_multi it doesn't. Why? If it is caching then it must be a bad caching, i guess... ------------------------------------------------------------------------ [2006-10-04 17:22:14] [EMAIL PROTECTED] All memory leaks are reported on shutdown. What you see is just the way zend memory manager works trying to reduce malloc/realloc/free calls and caching some memory. No bug here. ------------------------------------------------------------------------ [2006-10-04 16:01:03] eugen at id dot com dot ua Here is short script without external resources requipment: <?php echo "Initial memory usage: ".memory_get_usage()."\n"; $tasks = array( "http://www.google.com", "http://www.php.net" ); $curl_handles = array(); $mh = curl_multi_init(); reset($tasks); while (list($index, $row)=each($tasks)) { $cid = curl_init($row); curl_setopt($cid, CURLOPT_RETURNTRANSFER, 1); curl_multi_add_handle($mh, $cid); $curl_handles[ $index ] = $cid; } do { $n = curl_multi_exec($mh, $active); $info = curl_multi_info_read($mh); if (!empty($info)) { reset($curl_handles); while (list($task_id, $handle)=each($curl_handles)) { if ($handle == $info['handle']) { $done_task_id = $task_id; break; } } echo "Task $tasks[$done_task_id] completed\n"; $memory_usage = memory_get_usage(); // this should free up resources curl_close($info['handle']); $diff = memory_get_usage() - $memory_usage; echo "Memory usage was: $memory_usage, after curl_close: $diff bytes more\n"; } } while ($active); ?> ------------------------------------------------------------------------ [2006-10-04 15:35:51] [EMAIL PROTECTED] Thank you for this bug report. To properly diagnose the problem, we need a short but complete example script to be able to reproduce this bug ourselves. A proper reproducing script starts with <?php and ends with ?>, is max. 10-20 lines long and does not require any external resources such as databases, etc. If the script requires a database to demonstrate the issue, please make sure it creates all necessary tables, stored procedures etc. Please avoid embedding huge scripts into the report. >P.S. ìîæíî íà ðóññêîì :) No, it's a public system. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/39037 -- Edit this bug report at http://bugs.php.net/?id=39037&edit=1