GNU C Library master sources branch master updated. glibc-2.23-446-gbd49998

schwab@sourceware.org schwab@sourceware.org
Thu Jun 9 07:58:00 GMT 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  bd499987c63fae6dd52fc577c8aada54293336bc (commit)
      from  530bb2bf3b2972a960cbf4ed7ddd0cf4561b5f83 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bd499987c63fae6dd52fc577c8aada54293336bc

commit bd499987c63fae6dd52fc577c8aada54293336bc
Author: Andreas Schwab <schwab@suse.de>
Date:   Wed Mar 2 17:58:42 2016 +0100

    Fix nscd assertion failure in gc (bug 19755)
    
    If a GETxxBYyy request (for passwd or group) is running in parallel to
    an INVALIDATE request (for the same database) then in a particular order
    of events the garbage collector is not properly marking all used memory
    and fails an assertion:
    
       GETGRBYNAME (root)
    Haven't found "root" in group cache!
    add new entry "root" of type GETGRBYNAME for group to cache (first)
    handle_request: request received (Version = 2) from PID 7413
       INVALIDATE (group)
    pruning group cache; time 9223372036854775807
    considering GETGRBYNAME entry "root", timeout 1456763027
    add new entry "0" of type GETGRBYGID for group to cache
    remove GETGRBYNAME entry "root"
    nscd: mem.c:403: gc: Assertion `next_data == &he_data[db->head->nentries]' failed.
    
    Here the first call to cache_add added the GETGRBYNAME entry, which is
    immediately marked for collection by prune_cache.  Then the GETGRBYGID
    entry is added which shares the data packet with the first entry and
    therefore is marked as !first, while the marking look in prune_cache has
    already finished.  When the garbage collector runs, it only considers
    references by entries marked as first, missing the reference by the
    secondary entry.
    
    The only way to fix that is to prevent prune_cache from running while the
    two related entries are added.

diff --git a/ChangeLog b/ChangeLog
index 58b05e8..fd472f9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2016-06-09  Andreas Schwab  <schwab@suse.de>
+
+	[BZ #19755]
+	* nscd/pwdcache.c (cache_addpw): Lock prune_run_lock while adding
+	new entries in auto-propagate mode.
+	* nscd/grpcache.c (cache_addgr): Likewise.
+
 2016-06-09  Paul Pluzhnikov  <ppluzhnikov@gmail.com>
 
 	* test-skeleton.c (oom_error, xmalloc, xcalloc, xrealloc):
diff --git a/nscd/grpcache.c b/nscd/grpcache.c
index 3831170..8b9b13d 100644
--- a/nscd/grpcache.c
+++ b/nscd/grpcache.c
@@ -205,10 +205,19 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
       dataset = NULL;
 
       if (he == NULL)
-	dataset = (struct dataset *) mempool_alloc (db, total + n, 1);
+	{
+	  /* Prevent an INVALIDATE request from pruning the data between
+	     the two calls to cache_add.  */
+	  if (db->propagate)
+	    pthread_mutex_lock (&db->prune_run_lock);
+	  dataset = (struct dataset *) mempool_alloc (db, total + n, 1);
+	}
 
       if (dataset == NULL)
 	{
+	  if (he == NULL && db->propagate)
+	    pthread_mutex_unlock (&db->prune_run_lock);
+
 	  /* We cannot permanently add the result in the moment.  But
 	     we can provide the result as is.  Store the data in some
 	     temporary memory.  */
@@ -396,6 +405,8 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
 
 	out:
 	  pthread_rwlock_unlock (&db->lock);
+	  if (he == NULL && db->propagate)
+	    pthread_mutex_unlock (&db->prune_run_lock);
 	}
     }
 
diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
index 6dd6746..5ef8485 100644
--- a/nscd/pwdcache.c
+++ b/nscd/pwdcache.c
@@ -198,10 +198,19 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
       dataset = NULL;
 
       if (he == NULL)
-	dataset = (struct dataset *) mempool_alloc (db, total + n, 1);
+	{
+	  /* Prevent an INVALIDATE request from pruning the data between
+	     the two calls to cache_add.  */
+	  if (db->propagate)
+	    pthread_mutex_lock (&db->prune_run_lock);
+	  dataset = (struct dataset *) mempool_alloc (db, total + n, 1);
+	}
 
       if (dataset == NULL)
 	{
+	  if (he == NULL && db->propagate)
+	    pthread_mutex_unlock (&db->prune_run_lock);
+
 	  /* We cannot permanently add the result in the moment.  But
 	     we can provide the result as is.  Store the data in some
 	     temporary memory.  */
@@ -374,6 +383,8 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
 
 	out:
 	  pthread_rwlock_unlock (&db->lock);
+	  if (he == NULL && db->propagate)
+	    pthread_mutex_unlock (&db->prune_run_lock);
 	}
     }
 

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

Summary of changes:
 ChangeLog       |    7 +++++++
 nscd/grpcache.c |   13 ++++++++++++-
 nscd/pwdcache.c |   13 ++++++++++++-
 3 files changed, 31 insertions(+), 2 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources



More information about the Glibc-cvs mailing list