This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix nscd assertion failure in gc (bug 19755)
- From: Andreas Schwab <schwab at suse dot de>
- To: libc-alpha at sourceware dot org
- Date: Wed, 02 Mar 2016 18:13:48 +0100
- Subject: [PATCH] Fix nscd assertion failure in gc (bug 19755)
- Authentication-results: sourceware.org; auth=none
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."