128 lines
4.8 KiB
Diff
128 lines
4.8 KiB
Diff
From 7943443bb92fca6676922349fb12503a527cb6b1 Mon Sep 17 00:00:00 2001
|
|
From: Mark Reynolds <mreynolds@redhat.com>
|
|
Date: Thu, 15 May 2025 10:35:27 -0400
|
|
Subject: [PATCH] Issue 6782 - Improve paged result locking
|
|
|
|
Description:
|
|
|
|
When cleaning a slot, instead of mem setting everything to Zero and restoring
|
|
the mutex, manually reset all the values leaving the mutex pointer
|
|
intact.
|
|
|
|
There is also a deadlock possibility when checking for abandoned PR search
|
|
in opshared.c, and we were checking a flag value outside of the per_conn
|
|
lock.
|
|
|
|
Relates: https://github.com/389ds/389-ds-base/issues/6782
|
|
|
|
Reviewed by: progier & spichugi(Thanks!!)
|
|
---
|
|
ldap/servers/slapd/opshared.c | 10 +++++++++-
|
|
ldap/servers/slapd/pagedresults.c | 27 +++++++++++++++++----------
|
|
2 files changed, 26 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
|
|
index 7dc2d5983..14a7dcdfb 100644
|
|
--- a/ldap/servers/slapd/opshared.c
|
|
+++ b/ldap/servers/slapd/opshared.c
|
|
@@ -592,6 +592,14 @@ op_shared_search(Slapi_PBlock *pb, int send_result)
|
|
int32_t tlimit;
|
|
slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &tlimit);
|
|
pagedresults_set_timelimit(pb_conn, operation, (time_t)tlimit, pr_idx);
|
|
+ /* When using this mutex in conjunction with the main paged
|
|
+ * result lock, you must do so in this order:
|
|
+ *
|
|
+ * --> pagedresults_lock()
|
|
+ * --> pagedresults_mutex
|
|
+ * <-- pagedresults_mutex
|
|
+ * <-- pagedresults_unlock()
|
|
+ */
|
|
pagedresults_mutex = pageresult_lock_get_addr(pb_conn);
|
|
}
|
|
|
|
@@ -717,11 +725,11 @@ op_shared_search(Slapi_PBlock *pb, int send_result)
|
|
pr_search_result = pagedresults_get_search_result(pb_conn, operation, 1 /*locked*/, pr_idx);
|
|
if (pr_search_result) {
|
|
if (pagedresults_is_abandoned_or_notavailable(pb_conn, 1 /*locked*/, pr_idx)) {
|
|
+ pthread_mutex_unlock(pagedresults_mutex);
|
|
pagedresults_unlock(pb_conn, pr_idx);
|
|
/* Previous operation was abandoned and the simplepaged object is not in use. */
|
|
send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
|
|
rc = LDAP_SUCCESS;
|
|
- pthread_mutex_unlock(pagedresults_mutex);
|
|
goto free_and_return;
|
|
} else {
|
|
slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, pr_search_result);
|
|
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
|
|
index 642aefb3d..c3f3aae01 100644
|
|
--- a/ldap/servers/slapd/pagedresults.c
|
|
+++ b/ldap/servers/slapd/pagedresults.c
|
|
@@ -48,7 +48,6 @@ pageresult_lock_get_addr(Connection *conn)
|
|
static void
|
|
_pr_cleanup_one_slot(PagedResults *prp)
|
|
{
|
|
- PRLock *prmutex = NULL;
|
|
if (!prp) {
|
|
return;
|
|
}
|
|
@@ -56,13 +55,17 @@ _pr_cleanup_one_slot(PagedResults *prp)
|
|
/* sr is left; release it. */
|
|
prp->pr_current_be->be_search_results_release(&(prp->pr_search_result_set));
|
|
}
|
|
- /* clean up the slot */
|
|
- if (prp->pr_mutex) {
|
|
- /* pr_mutex is reused; back it up and reset it. */
|
|
- prmutex = prp->pr_mutex;
|
|
- }
|
|
- memset(prp, '\0', sizeof(PagedResults));
|
|
- prp->pr_mutex = prmutex;
|
|
+
|
|
+ /* clean up the slot except the mutex */
|
|
+ prp->pr_current_be = NULL;
|
|
+ prp->pr_search_result_set = NULL;
|
|
+ prp->pr_search_result_count = 0;
|
|
+ prp->pr_search_result_set_size_estimate = 0;
|
|
+ prp->pr_sort_result_code = 0;
|
|
+ prp->pr_timelimit_hr.tv_sec = 0;
|
|
+ prp->pr_timelimit_hr.tv_nsec = 0;
|
|
+ prp->pr_flags = 0;
|
|
+ prp->pr_msgid = 0;
|
|
}
|
|
|
|
/*
|
|
@@ -1007,7 +1010,8 @@ op_set_pagedresults(Operation *op)
|
|
|
|
/*
|
|
* pagedresults_lock/unlock -- introduced to protect search results for the
|
|
- * asynchronous searches.
|
|
+ * asynchronous searches. Do not call these functions while the PR conn lock
|
|
+ * is held (e.g. pageresult_lock_get_addr(conn))
|
|
*/
|
|
void
|
|
pagedresults_lock(Connection *conn, int index)
|
|
@@ -1045,6 +1049,8 @@ int
|
|
pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int index)
|
|
{
|
|
PagedResults *prp;
|
|
+ int32_t result;
|
|
+
|
|
if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
|
|
return 1; /* not abandoned, but do not want to proceed paged results op. */
|
|
}
|
|
@@ -1052,10 +1058,11 @@ pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int inde
|
|
pthread_mutex_lock(pageresult_lock_get_addr(conn));
|
|
}
|
|
prp = conn->c_pagedresults.prl_list + index;
|
|
+ result = prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
|
|
if (!locked) {
|
|
pthread_mutex_unlock(pageresult_lock_get_addr(conn));
|
|
}
|
|
- return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
|
|
+ return result;
|
|
}
|
|
|
|
int
|
|
--
|
|
2.49.0
|
|
|