|
|
3b7e51 |
From 240cfa58c62571b92640a385cfcce6d858cb00dc Mon Sep 17 00:00:00 2001
|
|
|
3b7e51 |
From: Thierry Bordaz <tbordaz@redhat.com>
|
|
|
3b7e51 |
Date: Wed, 30 May 2018 15:48:11 +0200
|
|
|
3b7e51 |
Subject: [PATCH] Ticket 48184 - clean up and delete connections at shutdown
|
|
|
3b7e51 |
(3rd)
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Bug description:
|
|
|
3b7e51 |
During shutdown we would not close connections.
|
|
|
3b7e51 |
In the past this may have just been an annoyance, but now with the way
|
|
|
3b7e51 |
nunc-stans works, io events can still trigger on open xeisting connectinos
|
|
|
3b7e51 |
during shutdown.
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Fix Description:
|
|
|
3b7e51 |
Because of NS dynamic it can happen that several jobs wants to work on the
|
|
|
3b7e51 |
same connection. In such case (a job is already set in c_job) we delay the
|
|
|
3b7e51 |
new job that will retry.
|
|
|
3b7e51 |
In addition:
|
|
|
3b7e51 |
- some call needed c_mutex
|
|
|
3b7e51 |
- test uninitialized nunc-stans in case of shutdown while startup is not completed
|
|
|
3b7e51 |
|
|
|
3b7e51 |
If it is not possible to schedule immediately a job it is sometime useless to wait:
|
|
|
3b7e51 |
- if the connection is already freed, just cancel the scheduled job
|
|
|
3b7e51 |
and do not register a new one
|
|
|
3b7e51 |
- If we are in middle of a shutdown we do not know if the
|
|
|
3b7e51 |
scheduled job is ns_handle_closure, so cancel the scheduled
|
|
|
3b7e51 |
job and schedule ns_handle_closure.
|
|
|
3b7e51 |
|
|
|
3b7e51 |
https://pagure.io/389-ds-base/issue/48184
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Reviewed by:
|
|
|
3b7e51 |
Original fix reviewed by Ludwig and Viktor
|
|
|
3b7e51 |
Second fix reviewed by Mark
|
|
|
3b7e51 |
Third fix reviewed by Mark
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Platforms tested: F26
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Flag Day: no
|
|
|
3b7e51 |
|
|
|
3b7e51 |
Doc impact: no
|
|
|
3b7e51 |
---
|
|
|
3b7e51 |
ldap/servers/slapd/connection.c | 10 +++--
|
|
|
3b7e51 |
ldap/servers/slapd/conntable.c | 2 +-
|
|
|
3b7e51 |
ldap/servers/slapd/daemon.c | 67 +++++++++++++++++++++++++--------
|
|
|
3b7e51 |
ldap/servers/slapd/proto-slap.h | 2 +-
|
|
|
3b7e51 |
4 files changed, 60 insertions(+), 21 deletions(-)
|
|
|
3b7e51 |
|
|
|
3b7e51 |
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
|
|
|
3b7e51 |
index 76e83112b..c54e7c26c 100644
|
|
|
3b7e51 |
--- a/ldap/servers/slapd/connection.c
|
|
|
3b7e51 |
+++ b/ldap/servers/slapd/connection.c
|
|
|
3b7e51 |
@@ -741,14 +741,18 @@ connection_acquire_nolock(Connection *conn)
|
|
|
3b7e51 |
|
|
|
3b7e51 |
/* returns non-0 if connection can be reused and 0 otherwise */
|
|
|
3b7e51 |
int
|
|
|
3b7e51 |
-connection_is_free(Connection *conn)
|
|
|
3b7e51 |
+connection_is_free(Connection *conn, int use_lock)
|
|
|
3b7e51 |
{
|
|
|
3b7e51 |
int rc;
|
|
|
3b7e51 |
|
|
|
3b7e51 |
- PR_EnterMonitor(conn->c_mutex);
|
|
|
3b7e51 |
+ if (use_lock) {
|
|
|
3b7e51 |
+ PR_EnterMonitor(conn->c_mutex);
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
rc = conn->c_sd == SLAPD_INVALID_SOCKET && conn->c_refcnt == 0 &&
|
|
|
3b7e51 |
!(conn->c_flags & CONN_FLAG_CLOSING);
|
|
|
3b7e51 |
- PR_ExitMonitor(conn->c_mutex);
|
|
|
3b7e51 |
+ if (use_lock) {
|
|
|
3b7e51 |
+ PR_ExitMonitor(conn->c_mutex);
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
|
|
|
3b7e51 |
return rc;
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
|
|
|
3b7e51 |
index f2f763dfa..114871d17 100644
|
|
|
3b7e51 |
--- a/ldap/servers/slapd/conntable.c
|
|
|
3b7e51 |
+++ b/ldap/servers/slapd/conntable.c
|
|
|
3b7e51 |
@@ -129,7 +129,7 @@ connection_table_get_connection(Connection_Table *ct, int sd)
|
|
|
3b7e51 |
break;
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
|
|
|
3b7e51 |
- if (connection_is_free(&(ct->c[index]))) {
|
|
|
3b7e51 |
+ if (connection_is_free(&(ct->c[index]), 1 /*use lock */)) {
|
|
|
3b7e51 |
break;
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
|
|
|
3b7e51 |
index 50e67474e..35cfe7de0 100644
|
|
|
3b7e51 |
--- a/ldap/servers/slapd/daemon.c
|
|
|
3b7e51 |
+++ b/ldap/servers/slapd/daemon.c
|
|
|
3b7e51 |
@@ -1699,7 +1699,8 @@ ns_connection_post_io_or_closing_try(Connection *conn)
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
|
|
|
3b7e51 |
/*
|
|
|
3b7e51 |
- * Cancel any existing ns jobs we have registered.
|
|
|
3b7e51 |
+ * A job was already scheduled.
|
|
|
3b7e51 |
+ * Let it be dispatched first
|
|
|
3b7e51 |
*/
|
|
|
3b7e51 |
if (conn->c_job != NULL) {
|
|
|
3b7e51 |
return 1;
|
|
|
3b7e51 |
@@ -1780,25 +1781,59 @@ ns_connection_post_io_or_closing_try(Connection *conn)
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
return 0;
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
+
|
|
|
3b7e51 |
+/*
|
|
|
3b7e51 |
+ * Tries to schedule I/O for this connection
|
|
|
3b7e51 |
+ * If the connection is already busy with a scheduled I/O
|
|
|
3b7e51 |
+ * it can wait until scheduled I/O is dispatched
|
|
|
3b7e51 |
+ *
|
|
|
3b7e51 |
+ * caller must hold c_mutex
|
|
|
3b7e51 |
+ */
|
|
|
3b7e51 |
void
|
|
|
3b7e51 |
ns_connection_post_io_or_closing(Connection *conn)
|
|
|
3b7e51 |
{
|
|
|
3b7e51 |
while (ns_connection_post_io_or_closing_try(conn)) {
|
|
|
3b7e51 |
- /* we should retry later */
|
|
|
3b7e51 |
-
|
|
|
3b7e51 |
- /* We are not suppose to work immediately on the connection that is taken by
|
|
|
3b7e51 |
- * another job
|
|
|
3b7e51 |
- * release the lock and give some time
|
|
|
3b7e51 |
- */
|
|
|
3b7e51 |
-
|
|
|
3b7e51 |
- if (CONN_NEEDS_CLOSING(conn) && conn->c_ns_close_jobs) {
|
|
|
3b7e51 |
- return;
|
|
|
3b7e51 |
- } else {
|
|
|
3b7e51 |
- PR_ExitMonitor(conn->c_mutex);
|
|
|
3b7e51 |
- DS_Sleep(PR_MillisecondsToInterval(100));
|
|
|
3b7e51 |
-
|
|
|
3b7e51 |
- PR_EnterMonitor(conn->c_mutex);
|
|
|
3b7e51 |
- }
|
|
|
3b7e51 |
+ /* Here a job is currently scheduled (c->job is set) and not yet dispatched
|
|
|
3b7e51 |
+ * Job can be either:
|
|
|
3b7e51 |
+ * - ns_handle_closure
|
|
|
3b7e51 |
+ * - ns_handle_pr_read_ready
|
|
|
3b7e51 |
+ */
|
|
|
3b7e51 |
+
|
|
|
3b7e51 |
+ if (connection_is_free(conn, 0)) {
|
|
|
3b7e51 |
+ PRStatus shutdown_status;
|
|
|
3b7e51 |
+
|
|
|
3b7e51 |
+ /* The connection being freed,
|
|
|
3b7e51 |
+ * It means that ns_handle_closure already completed and the connection
|
|
|
3b7e51 |
+ * is no longer on the active list.
|
|
|
3b7e51 |
+ * The scheduled job is useless and scheduling a new one as well
|
|
|
3b7e51 |
+ */
|
|
|
3b7e51 |
+ shutdown_status = ns_job_done(conn->c_job);
|
|
|
3b7e51 |
+ if (shutdown_status != PR_SUCCESS) {
|
|
|
3b7e51 |
+ slapi_log_err(SLAPI_LOG_CRIT, "ns_connection_post_io_or_closing", "Failed cancel a job on a freed connection %d !\n", conn->c_sd);
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
+ conn->c_job = NULL;
|
|
|
3b7e51 |
+ return;
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
+ if (g_get_shutdown() && CONN_NEEDS_CLOSING(conn)) {
|
|
|
3b7e51 |
+ PRStatus shutdown_status;
|
|
|
3b7e51 |
+
|
|
|
3b7e51 |
+ /* This is shutting down cancel any scheduled job to register ns_handle_closure
|
|
|
3b7e51 |
+ */
|
|
|
3b7e51 |
+ shutdown_status = ns_job_done(conn->c_job);
|
|
|
3b7e51 |
+ if (shutdown_status != PR_SUCCESS) {
|
|
|
3b7e51 |
+ slapi_log_err(SLAPI_LOG_CRIT, "ns_connection_post_io_or_closing", "Failed to cancel a job during shutdown %d !\n", conn->c_sd);
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
+ conn->c_job = NULL;
|
|
|
3b7e51 |
+ continue;
|
|
|
3b7e51 |
+ }
|
|
|
3b7e51 |
+
|
|
|
3b7e51 |
+ /* We are not suppose to work immediately on the connection that is taken by
|
|
|
3b7e51 |
+ * another job
|
|
|
3b7e51 |
+ * release the lock and give some time
|
|
|
3b7e51 |
+ */
|
|
|
3b7e51 |
+ PR_ExitMonitor(conn->c_mutex);
|
|
|
3b7e51 |
+ DS_Sleep(PR_MillisecondsToInterval(100));
|
|
|
3b7e51 |
+ PR_EnterMonitor(conn->c_mutex);
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
}
|
|
|
3b7e51 |
|
|
|
3b7e51 |
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
|
|
|
3b7e51 |
index b13334ad1..f54bc6bc5 100644
|
|
|
3b7e51 |
--- a/ldap/servers/slapd/proto-slap.h
|
|
|
3b7e51 |
+++ b/ldap/servers/slapd/proto-slap.h
|
|
|
3b7e51 |
@@ -1431,7 +1431,7 @@ int connection_acquire_nolock(Connection *conn);
|
|
|
3b7e51 |
int connection_acquire_nolock_ext(Connection *conn, int allow_when_closing);
|
|
|
3b7e51 |
int connection_release_nolock(Connection *conn);
|
|
|
3b7e51 |
int connection_release_nolock_ext(Connection *conn, int release_only);
|
|
|
3b7e51 |
-int connection_is_free(Connection *conn);
|
|
|
3b7e51 |
+int connection_is_free(Connection *conn, int user_lock);
|
|
|
3b7e51 |
int connection_is_active_nolock(Connection *conn);
|
|
|
3b7e51 |
#if defined(USE_OPENLDAP)
|
|
|
3b7e51 |
ber_slen_t openldap_read_function(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len);
|
|
|
3b7e51 |
--
|
|
|
3b7e51 |
2.17.0
|
|
|
3b7e51 |
|