ID:               41127
 Updated by:       [EMAIL PROTECTED]
 Reported By:      ktk at bigfoot dot com
-Status:           Assigned
+Status:           Closed
 Bug Type:         LDAP related
 Operating System: Slackware GNU/Linux
 PHP Version:      5.2.1
 Assigned To:      jani
 New Comment:

This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.




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

[2007-04-23 15:22:06] [EMAIL PROTECTED]

tony: I had written a patch like that before I posted my previous
comment and it didn't appear to work. I guess I'll try to play with it
some more. Got a reference extension I could peek at any chance?

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

[2007-04-18 07:55:24] [EMAIL PROTECTED]

>AFAIK there's no way to garbage collect resources once their
>reference in PHP is gone.
Surely there is. Almost all resources have their destructors which are
called when the last reference is gone.
But le_ber_entry is missing a destructor:
le_ber_entry = zend_register_list_destructors_ex(NULL <-- no dtor ,
NULL, "ldap ber entry", module_number);

As far as I understand, this resource depends on both link and entry
resources, so you should keep a reference to them and increase their
reference count when creating and decrease it when destroying.

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

[2007-04-18 01:01:42] [EMAIL PROTECTED]

The problem is that ldap_first_attribute is defined as follows:

char *ldap_first_attribute(LDAP *ld, LDAPMessage *entry, BerElement
**berptr )

And you have to pass berptr back to each ldap_next_attribute() call you
make. So the ldap extension registers the berptr as a resource since
there is no native PHP type for it. AFAIK there's no way to garbage
collect resources once their reference in PHP is gone.

The memory is not actually leaking, it's just creating a bunch of
resources. The only suggestion I have is to create a function
ldap_free_attribute() which can free the passed in resource.

This issue is similar to the mysql issue when you don't free the
results from mysql_query() operations and they just keep allocating
resources...

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

[2007-04-17 22:26:30] ktk at bigfoot dot com

Description:
------------
PHP "leaks" memory in the ldap_{first|next}_attribute() functions. 
Interestingly, the ldap_get_attributes() function does not leak.
I put "leaks" in quotes because the leak() function does not detect the
issue; presumably, the memory is programmatically freed, just not until
PHP exits.

If one does something like:
while (true) {
  $s = ldap_search($link, $base, $filter, $atts);
  for ($e = ldap_first_entry($link, $s); $e != false;
       $e = ldap_next_entry($link, $e)) {
    for ($a = ldap_first_attribute($link, $e, $ber); $a;
         $a = ldap_next_attribute($link, $e, $ber)) {  }
  }
  ldap_free_result($s);
}
then PHP will eat all available memory and bomb with a memory
allocation error.  Unbinding and re-binding has no effect.

Reproduce code:
---------------
A working 51-line script that shows memory allocation versus iteration
count can be found at this url:
http://enterprise.bidmc.harvard.edu/private/php-bugs/ldap-leak-test.php

There are a few variables you can set/tweak at the top to get it to
point at whatever LDAP server you have handy.  Choosing a search filter
that returns a dozen or so entries is ideal for showing the runaway
memory.  You can also change the "$fail" variable from True to False,
which will stop the leak by way of using the roughly-equivalent function
ldap_get_attributes().

Expected result:
----------------
PHP's memory subsystem should collect and re-use the freed memory. 
After some number of iterations of the test script (typically 100 to
500) the results reported by memory_get_usage() should remain stable.

Actual result:
--------------
The results reported by memory_get_usage() increase fairly linearly
with each iteration until memory_limit is reached, whence the script
bombs.


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


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

Reply via email to