From 43c4d1d06a33bd2919e730128083e2ab86565a32 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Fri, 19 Jun 2009 23:55:56 +0000
Subject: [PATCH] ITS#6177

---
 CHANGES                        |  1 +
 servers/slapd/back-bdb/cache.c | 21 ++++++++++++++++++++-
 servers/slapd/back-bdb/dn2id.c | 24 ++++++++++++------------
 3 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/CHANGES b/CHANGES
index 52b1fffef5..8befeffa7d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -29,6 +29,7 @@ OpenLDAP 2.4.17 Engineering
 	Fixed slapd some abandon and cancel race conditions (ITS#6104)
 	Fixed slapd tls context after changes (ITS#6135)
 	Fixed slapd-bdb/hdb adjust dncachesize if too low (ITS#6176)
+	Fixed slapd-bdb/hdb crashes during delete (ITS#6177)
 	Fixed slapd-hdb freeing of already freed entries (ITS#6074)
 	Fixed slapd-hdb entryinfo cleanup (ITS#6088)
 	Fixed slapd-hdb dncache lockups (ITS#6095)
diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c
index 5b79b665a2..5d36a2db29 100644
--- a/servers/slapd/back-bdb/cache.c
+++ b/servers/slapd/back-bdb/cache.c
@@ -979,6 +979,9 @@ load1:
 			if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
 				rc = DB_NOTFOUND;
 				bdb_cache_entry_db_unlock( bdb, lock );
+				bdb_cache_entryinfo_lock( *eip );
+				(*eip)->bei_finders--;
+				bdb_cache_entryinfo_unlock( *eip );
 			} else if ( rc == 0 ) {
 				if ( load ) {
 					if ( !ep) {
@@ -1336,7 +1339,7 @@ bdb_cache_delete(
     DB_LOCK	*lock )
 {
 	EntryInfo *ei = BEI(e);
-	int	rc;
+	int	rc, busy = 0;
 
 	assert( e->e_private != NULL );
 
@@ -1346,8 +1349,24 @@ bdb_cache_delete(
 	/* Set this early, warn off any queriers */
 	ei->bei_state |= CACHE_ENTRY_DELETED;
 
+	if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED |
+		CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) ||
+		ei->bei_finders > 0 )
+		busy = 1;
+
 	bdb_cache_entryinfo_unlock( ei );
 
+	while ( busy ) {
+		ldap_pvt_thread_yield();
+		busy = 0;
+		bdb_cache_entryinfo_lock( ei );
+		if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED |
+			CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) ||
+			ei->bei_finders > 0 )
+			busy = 1;
+		bdb_cache_entryinfo_unlock( ei );
+	}
+
 	/* Get write lock on the data */
 	rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock );
 	if ( rc ) {
diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c
index 24c8266676..2d1748c328 100644
--- a/servers/slapd/back-bdb/dn2id.c
+++ b/servers/slapd/back-bdb/dn2id.c
@@ -1156,18 +1156,18 @@ gotit:
 					if ( bdb_cache_find_id( cx->op, cx->txn, cx->id, &cx->ei,
 						ID_NOENTRY, NULL ))
 						continue;
-					if ( !cx->ei ||
-						( cx->ei->bei_state & CACHE_ENTRY_NO_KIDS ))
-						continue;
-
-					ei2 = cx->ei;
-					BDB_ID2DISK( cx->id, &cx->nid );
-					hdb_dn2idl_internal( cx );
-					if ( !BDB_IDL_IS_ZERO( cx->tmp ))
-						nokids = 0;
-					bdb_cache_entryinfo_lock( ei2 );
-					ei2->bei_finders--;
-					bdb_cache_entryinfo_unlock( ei2 );
+					if ( cx->ei ) {
+						ei2 = cx->ei;
+						if ( !( ei2->bei_state & CACHE_ENTRY_NO_KIDS )) {
+							BDB_ID2DISK( cx->id, &cx->nid );
+							hdb_dn2idl_internal( cx );
+							if ( !BDB_IDL_IS_ZERO( cx->tmp ))
+								nokids = 0;
+						}
+						bdb_cache_entryinfo_lock( ei2 );
+						ei2->bei_finders--;
+						bdb_cache_entryinfo_unlock( ei2 );
+					}
 				}
 				cx->depth--;
 				cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
-- 
GitLab