Blame SOURCES/0087-Ticket-48184-clean-up-and-delete-connections-at-shut.patch

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