lists.arthurdejong.org
RSS feed

Re: [nssldap] libnss_ldap leaks memory - causes nscd to grow

[Date Prev][Date Next] [Thread Prev][Thread Next]

Re: [nssldap] libnss_ldap leaks memory - causes nscd to grow





Luke Howard wrote:
Doug,

The connection has changed a bit for 266. I'll send you a snapshot when Howard Wilkinson has finished testing, and then we can see how your changes apply to it.

OK, Any idea when?

This problem has been reported by others, as nscd problem. The use of
valgrind for testing might be helpful for your testing too.

The heart of the patch is the addition of the two lines

  line 1236:  if (__session.ls_state == LS_UNINITIALIZED) {
  line 1356:  }


-- Luke

On 18/03/2010, at 8:10 PM, Douglas E. Engert wrote:

The following was submitted as bugs to Ubuntu:
 https://bugs.launchpad.net/ubuntu/+source/libnss-ldap/+bug/292971
and original source developers:
 http://bugzilla.padl.com/show_bug.cgi?id=418

Using valgrind with nscd might also be of interest to others.


A memory leak in libnss-ldap over time can cause the nscd
process to grow extremely large. For example one nscd
process that had been running for three months was using
6GB of swap!

The problem is in the original Padl nss-ldap in at least versions
258, 261 and 265. Ubuntu Hardy uses 258, Karmic uses 261, and
the Padl current release is 265.


The ldap-nss.c do_init() may be called more then once,
to initialize an ldap session  and save the session in
in __session.ls_conn and set the __session.ls_stat = LD_INITIALIZED
But it does not check the state  to see if has be initialized,
and at line 1239: __session.ls_conn = NULL;

The attached patch to to the libnss-ldap_261-2.1Ubuntu4 fixes
the problem, by testing __session.ls_stat == LD_INITIALIZED

The ldap-nss.c also has a patch to call do_close twice that
I had previously turned it to Padl and is now in 265.

For testing purposes, the patch also adds atexit(do_atexit);
and a do_atexit routine to call do_close. This will then cause
the last session to be be freed. This make it much easier to
use valgrind to check for memory leaks. (in the nscd.c in lib6c
the _exit was change to exit so the atexit would be called.)

Debug versions of nscd and libnss-ldap where created, and
and used with valgrind to track down the memory leaks.
Attached is a script used with valgrind. The LD_PRELOAD was
needed so dynamic libs would not be unloaded, and valgrind
could find the symbol tables.

--

  Douglas E. Engert  <DEEngert@anl.gov <DEEngert [at] anl.gov>>
  Argonne National Laboratory
  9700 South Cass Avenue
  Argonne, Illinois  60439
  (630) 252-5444


--- libc6/eglibc-2.10.1/nscd/,nscd.c 2009-07-29 11:29:54.000000000 -0500
+++ libc6/eglibc-2.10.1/nscd/nscd.c 2010-03-15 15:02:53.429225933 -0500
@@ -491,7 +491,9 @@
msync (dbs[cnt].head, dbs[cnt].memsize, MS_ASYNC);
    }

-  _exit (EXIT_SUCCESS);
+/* for testing to let libnss-ldap cleanup, we use exit */
+ exit (EXIT_SUCCESS);
+//  _exit (EXIT_SUCCESS);
}

/* Returns 1 if the process in pid file FILE is running, 0 if not.  */


--- libnss-ldap/libnss-ldap-261/build-tree/nss_ldap-261/,ldap-nss.c 2010-03-15 10:04:47.593727549 -0500 +++ libnss-ldap/libnss-ldap-261/build-tree/nss_ldap-261/ldap-nss.c 2010-03-17 16:04:16.165226755 -0500
@@ -184,6 +184,7 @@
static void do_atfork_setup (void);
#endif

+static void do_atexit (void); /* allow exit to cleanup to help valgrind */
/*
 * Close the global session, sending an unbind.
 */
@@ -553,11 +554,25 @@
(void) __libc_atfork (do_atfork_prepare, do_atfork_parent, do_atfork_child);
#endif

+atexit(do_atexit); /* allow exit to cleanup to help valgrind */
+
  debug ("<== do_atfork_setup");
}
#endif

/*
+ * allow exit to cleanup to help valgrind
+ */
+void
+do_atexit (void)
+{
+  debug ("<== do_atexit");
+  _nss_ldap_enter();
+  do_close();
+  debug ("==> do_atexit (should be no more activity)");
+}
+
+/*
 * Acquires global lock, blocks SIGPIPE.
 */
void
@@ -1107,6 +1122,7 @@

  debug ("==> do_init");

+
  if (_nss_ldap_validateconfig (__config) != NSS_SUCCESS)
    {
      do_close ();
@@ -1236,9 +1252,9 @@
}
    }

-  __session.ls_conn = NULL;
+/* LOOKS LIKE A PROBLEM. COULD BE INITIALIZED, BUT NOT CONNECTED */
+  if (__session.ls_state == LS_UNINITIALIZED) {
  __session.ls_timestamp = 0;
-  __session.ls_state = LS_UNINITIALIZED;

#if defined(HAVE_PTHREAD_ONCE) && defined(HAVE_PTHREAD_ATFORK)
  if (pthread_once (&__once, do_atfork_setup) != 0)
@@ -1357,6 +1373,10 @@
  __session.ls_state = LS_INITIALIZED;

  debug ("<== do_init (initialized session)");
+  } /* if already initialized  but not connected */
+  else {
+    debug ("<== do_init (already initialized)");
+  }

  return NSS_SUCCESS;
}
@@ -1577,6 +1597,7 @@
}
      else
{
+ syslog(LOG_ERR, "nss-ldap: do_open: do_start_tls failed:stat=%d", stat);
 do_close ();
 debug ("<== do_open (TLS startup failed)");
 return stat;
@@ -2472,6 +2493,7 @@
#endif /* LDAP_OPT_ERROR_NUMBER */
syslog (LOG_AUTHPRIV | LOG_ERR, "nss_ldap: could not get LDAP result - %s",
 ldap_err2string (rc));
+          do_close();
 stat = NSS_UNAVAIL;
 break;
case LDAP_RES_SEARCH_ENTRY:
@@ -2507,6 +2529,7 @@
 syslog (LOG_AUTHPRIV | LOG_ERR,
 "nss_ldap: could not get LDAP result - %s",
 ldap_err2string (rc));
+                  do_close();
}
     else if (resultControls != NULL)
{


#   #remove this# !/bin/bash
# Above line was modified to would make it via e-mail filters
# that wont allow schee scripts
#
# my options
#

LOG=/tmp/valgrind.nscd.exit.$$
echo log=$LOG
LOG2=/tmp/valgrind.nscd.exit.stderr.$$

export LD_LIBRARY_PATH=/usr/lib/debug/lib

LD_PRELOAD=/lib/libnss_ldap-2.10.1.so:/lib/tls/i686/cmov/libnss_compat-2.10.1.so:/lib/tls/i686/cmov/libnss_files-2.10.1.so:/lib/tls/i686/cmov/libnss_dns-2.10.1.so \
/usr/bin/valgrind -v --log-file=$LOG \
--leak-check=full --leak-resolution=high \
--show-reachable=yes \
--num-callers=40 --track-origins=yes\
/home/rootdee/source/libc6/eglibc-2.10.1/build-tree/i386-libc/nscd/nscd\
2> $LOG2


--
www.padl.com <http://www.padl.com> | www.thisismagnolia.net <http://www.thisismagnolia.net>


--

 Douglas E. Engert  <DEEngert@anl.gov>
 Argonne National Laboratory
 9700 South Cass Avenue
 Argonne, Illinois  60439
 (630) 252-5444