URL: https://github.com/freeipa/bind-dyndb-ldap/pull/6
Author: tomaskrizek
 Title: #6: handle termination of syncrepl watcher thread
Action: synchronized

To pull the PR as Git branch:
git remote add ghbind-dyndb-ldap https://github.com/freeipa/bind-dyndb-ldap
git fetch ghbind-dyndb-ldap pull/6/head:pr6
git checkout pr6
From 8712baf2f7d45f895d8a418d2d4305ead0f7e82f Mon Sep 17 00:00:00 2001
From: Tomas Krizek <tkri...@redhat.com>
Date: Mon, 19 Dec 2016 12:39:07 +0100
Subject: [PATCH] handle termination of syncrepl watcher thread

In some cases, the thread could have been already terminated and
sending a signal to the thread using pthread_kill() would result in an
error. Now if the thread has already been terminated for some reason,
only an error message is logged.

https://fedorahosted.org/bind-dyndb-ldap/ticket/149

Reviewed-By: Petr Spacek <pspa...@redhat.com>
Reviewed-By: Thierry Bordaz <tbor...@redhat.com>
---
 src/ldap_helper.c | 46 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index a11751d..5de9f69 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -668,6 +668,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name, const char *parameters,
 	result = isc_thread_create(ldap_syncrepl_watcher, ldap_inst,
 				   &ldap_inst->watcher);
 	if (result != ISC_R_SUCCESS) {
+		ldap_inst->watcher = 0;
 		log_error("Failed to create syncrepl watcher thread");
 		goto cleanup;
 	}
@@ -684,6 +685,38 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name, const char *parameters,
 }
 #undef PRINT_BUFF_SIZE
 
+/**
+ * Send SIGUSR1 to the SyncRepl watcher thread and wait for it to terminate.
+ *
+ * If the thread has already been terminated and a signal can't be sent to it,
+ * log an error instead. The thread is still joined, but since it is no longer
+ * running, it is instantaneous and doesn't block.
+ *
+ * @param[in]  ldap_inst	LDAP instance with ID of watcher thread
+ */
+static void ATTR_NONNULLS
+ldap_syncrepl_watcher_shutdown(ldap_instance_t *ldap_inst)
+{
+	REQUIRE(ldap_inst != NULL);
+
+	ldap_inst->exiting = ISC_TRUE;
+	/*
+	 * Wake up the watcher thread. This might look like a hack
+	 * but isc_thread_t is actually pthread_t and libisc don't
+	 * have any isc_thread_kill() func.
+	 *
+	 * We use SIGUSR1 to not to interfere with any signal
+	 * used by BIND itself.
+	 */
+	if (pthread_kill(ldap_inst->watcher, SIGUSR1) != 0) {
+		log_error("unable to send signal to SyncRepl watcher thread "
+				  "(already terminated?)");
+	}
+
+	RUNTIME_CHECK(isc_thread_join(ldap_inst->watcher, NULL)
+		      == ISC_R_SUCCESS);
+}
+
 void
 destroy_ldap_instance(ldap_instance_t **ldap_instp)
 {
@@ -696,18 +729,7 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp)
 		return;
 
 	if (ldap_inst->watcher != 0) {
-		ldap_inst->exiting = ISC_TRUE;
-		/*
-		 * Wake up the watcher thread. This might look like a hack
-		 * but isc_thread_t is actually pthread_t and libisc don't
-		 * have any isc_thread_kill() func.
-		 *
-		 * We use SIGUSR1 to not to interfere with any signal
-		 * used by BIND itself.
-		 */
-		REQUIRE(pthread_kill(ldap_inst->watcher, SIGUSR1) == 0);
-		RUNTIME_CHECK(isc_thread_join(ldap_inst->watcher, NULL)
-			      == ISC_R_SUCCESS);
+		ldap_syncrepl_watcher_shutdown(ldap_inst);
 		ldap_inst->watcher = 0;
 	}
 
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to