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 51e2bb27c524224493161dbc7db00c2893fd1b21 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 --- src/ldap_helper.c | 45 +++++++++++++++++++++++++++++++++------------ src/ldap_helper.h | 1 + 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index a11751d..9362849 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; } @@ -696,18 +697,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; } @@ -747,6 +737,37 @@ destroy_ldap_instance(ldap_instance_t **ldap_instp) *ldap_instp = NULL; } +/** + * 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 + */ +void 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); +} + static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT new_ldap_connection(ldap_pool_t *pool, ldap_connection_t **ldap_connp) { diff --git a/src/ldap_helper.h b/src/ldap_helper.h index 6cfece5..abc8220 100644 --- a/src/ldap_helper.h +++ b/src/ldap_helper.h @@ -45,6 +45,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name, const char *parameters, const char *file, unsigned long line, const dns_dyndbctx_t *dctx, ldap_instance_t **ldap_instp) ATTR_NONNULLS; void destroy_ldap_instance(ldap_instance_t **ldap_inst) ATTR_NONNULLS; +void ldap_syncrepl_watcher_shutdown(ldap_instance_t *ldap_inst) ATTR_NONNULLS; isc_result_t ldap_delete_zone2(ldap_instance_t *inst, dns_name_t *name, isc_boolean_t lock)
-- 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