andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 4 months ago
Clone
Blob Blame History Raw
From 57852e959b6f121eefb0c0c4ff2adc79b2125934 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Fri, 12 Sep 2014 11:14:24 -0400
Subject: [PATCH] Ticket 47750 - Fix incomplete backport to 1.3.1/1.2.11

Description:  An incomplete backport of 47750 to 1.3.1 and 1.2.11 caused
              a memory leak.

https://fedorahosted.org/389/ticket/47750

Reviewed by: rmeggins(Thanks!)

(cherry picked from commit 0b5f0d68233cec976d57597d1c810b79c62528a5)
(cherry picked from commit 649e726834820abc0ab6bdfb90806e2dec4391db)
---
 ldap/servers/slapd/back-ldbm/ldbm_delete.c | 74 +++++++++++-------------------
 1 file changed, 26 insertions(+), 48 deletions(-)

diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 23529dc..32c119c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -673,54 +673,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
 				goto error_return;
 			}
 			if (tombstone_in_cache) {
-				retval = cache_replace(&inst->inst_cache, e, tombstone);
-				if (retval) {
-					LDAPDebug(LDAP_DEBUG_CACHE, "ldbm_back_delete: cache_replace failed (%d): %s --> %s\n",
-					          retval, slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn(tombstone->ep_entry));
-					retval= -1;
-					DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
-					goto error_return;
-				} else {
-					e_in_cache = 0;
-				}
-			} else {
-				struct backentry *imposter = NULL;
-				retval = CACHE_ADD(&inst->inst_cache, tombstone, &imposter);
-				if (retval > 0) {
-					if (imposter) {
-						/* 
-						 * The same tombstone entry (different Slapi_Entry) is already
-						 * generated and set to cache.  Back off. 
-						 */
-						CACHE_RETURN(&inst->inst_cache, &imposter);
-						LDAPDebug1Arg(LDAP_DEBUG_CACHE, 
-						              "ldbm_delete: cache add: same DN tombstone in cache: %s\n",
-						              slapi_entry_get_dn(tombstone->ep_entry));
-					} else {
-						/* 
-						 * The same tombstone entry (same Slapi_Entry) is being created.
-						 * Something is wrong.  We should clean it up from the cache,
-						 * and back off.
-						 */
-						tombstone_in_cache = 1;
-						LDAPDebug1Arg(LDAP_DEBUG_CACHE, 
-						              "ldbm_delete: cache add: same tombstone in cache: %s\n",
-						              slapi_entry_get_dn(tombstone->ep_entry));
-					}
-					retval= -1;
-					DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
-					goto error_return;
-				} else if (retval < 0) {
-					LDAPDebug1Arg(LDAP_DEBUG_CACHE, 
-					              "ldbm_delete: cache add: Add %s failed.\n",
-					              slapi_entry_get_dn(tombstone->ep_entry));
-					/* Complete add error */
-					retval= -1;
-					DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
-					goto error_return;
-				}
-			}
-			if (tombstone_in_cache) {
 				/* tombstone was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
 				   and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
 				   drop the extra ref added by cache_replace */
@@ -1130,6 +1082,16 @@ ldbm_back_delete( Slapi_PBlock *pb )
 		goto error_return;
 	}
 
+	if (create_tombstone_entry) {
+		retval = cache_replace(&inst->inst_cache, e, tombstone);
+		if (retval) {
+			LDAPDebug(LDAP_DEBUG_CACHE, "ldbm_back_delete: cache_replace failed (%d): %s --> %s\n",
+			        retval, slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn(tombstone->ep_entry));
+			retval= -1;
+			goto error_return;
+		}
+	}
+
 	/* call the transaction post delete plugins just before the commit */
 	if (plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN)) {
 		LDAPDebug0Args( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN plugin "
@@ -1333,6 +1295,22 @@ common_return:
 		plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_DELETE_FN);
 	}
 
+	if (e) {
+		if (e_in_cache) {
+			if (remove_e_from_cache) {
+				/* The entry is already transformed to a tombstone. */
+				CACHE_REMOVE( &inst->inst_cache, e );
+			}
+		}
+		cache_unlock_entry( &inst->inst_cache, e );
+		CACHE_RETURN( &inst->inst_cache, &e );
+		/*
+		 * e is unlocked and no longer in cache.
+		 * It could be freed at any moment.
+		 */
+		e = NULL;
+	}
+
 	if (ruv_c_init) {
 		modify_term(&ruv_c, be);
 	}
-- 
1.9.3