This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] 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.

	[BZ #19755]
	* nscd/mem.c (gc): Consider all references to the same data packet.
---
 nscd/mem.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/nscd/mem.c b/nscd/mem.c
index 1aafd37..49a3b60 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -175,14 +175,15 @@ gc (struct database_dyn *db)
 	  /* This is the hash entry itself.  */
 	  markrange (mark, run, sizeof (struct hashentry));
 
-	  /* Add the information for the data itself.  We do this
-	     only for the one special entry marked with FIRST.  */
-	  if (he[cnt]->first)
-	    {
-	      struct datahead *dh
-		= (struct datahead *) (db->data + he[cnt]->packet);
-	      markrange (mark, he[cnt]->packet, dh->allocsize);
-	    }
+	  /* Add the information for the data itself.  We need to do this
+	     for all entries that point to the same data packet, not only
+	     the one marked as first.  Otherwise if the entry marked as
+	     first has already been collected while the secondary entry
+	     was added we may miss the reference from the latter one.
+	     This can happen when processing an INVALIDATE request.  */
+	  struct datahead *dh
+	    = (struct datahead *) (db->data + he[cnt]->packet);
+	  markrange (mark, he[cnt]->packet, dh->allocsize);
 
 	  run = he[cnt]->next;
 
-- 
2.7.2

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]