You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2016/05/11 17:25:22 UTC

qpid-proton git commit: PROTON-992: Make cyrus sasl initialisation/shutdown thread safe

Repository: qpid-proton
Updated Branches:
  refs/heads/master 12ebe05a4 -> 1e9e243a3


PROTON-992: Make cyrus sasl initialisation/shutdown thread safe


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1e9e243a
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1e9e243a
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1e9e243a

Branch: refs/heads/master
Commit: 1e9e243a37acca22b5a77177cc1ab4d06ba4b2ec
Parents: 12ebe05
Author: Andrew Stitcher <as...@apache.org>
Authored: Tue May 3 16:40:21 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed May 11 13:51:31 2016 +0100

----------------------------------------------------------------------
 proton-c/CMakeLists.txt        |  2 +-
 proton-c/src/sasl/cyrus_sasl.c | 77 +++++++++++++++++++++++++++++++------
 2 files changed, 67 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1e9e243a/proton-c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt
index 372e67c..8219256 100644
--- a/proton-c/CMakeLists.txt
+++ b/proton-c/CMakeLists.txt
@@ -105,7 +105,7 @@ endif(PN_WINAPI)
 if (SASL_IMPL STREQUAL cyrus)
   set(pn_sasl_impl src/sasl/sasl.c src/sasl/cyrus_sasl.c)
   include_directories (${CYRUS_SASL_INCLUDE_DIR})
-  set(SASL_LIB ${CYRUS_SASL_LIBRARY})
+  set(SASL_LIB ${CYRUS_SASL_LIBRARY} -lpthread)
 elseif (SASL_IMPL STREQUAL none)
   set(pn_sasl_impl src/sasl/sasl.c src/sasl/none_sasl.c)
 endif ()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1e9e243a/proton-c/src/sasl/cyrus_sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/cyrus_sasl.c b/proton-c/src/sasl/cyrus_sasl.c
index 4af1f52..b1e2e03 100644
--- a/proton-c/src/sasl/cyrus_sasl.c
+++ b/proton-c/src/sasl/cyrus_sasl.c
@@ -25,6 +25,7 @@
 #include "engine/engine-internal.h"
 
 #include <sasl/sasl.h>
+#include <pthread.h>
 
 // If the version of Cyrus SASL is too early for sasl_client_done()/sasl_server_done()
 // don't do any global clean up as it's not safe to use just sasl_done() for an
@@ -102,17 +103,72 @@ static const sasl_callback_t pni_user_callbacks[] = {
     {SASL_CB_LIST_END, NULL, NULL},
 };
 
+// Machinery to initialise the cyrus library only once even in a multithreaded environment
+// Relies on pthreads.
+static char *pni_cyrus_config_dir = NULL;
+static const char *pni_cyrus_config_name = "proton-server";
+static pthread_mutex_t pni_cyrus_mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool pni_cyrus_client_started = false;
+static bool pni_cyrus_server_started = false;
+
+__attribute__((destructor))
+static void pni_cyrus_finish(void) {
+  pthread_mutex_lock(&pni_cyrus_mutex);
+  if (pni_cyrus_client_started) sasl_client_done();
+  if (pni_cyrus_server_started) sasl_server_done();
+  pthread_mutex_unlock(&pni_cyrus_mutex);
+}
+
+static int pni_cyrus_client_init_rc = SASL_OK;
+static void pni_cyrus_client_once(void) {
+  pthread_mutex_lock(&pni_cyrus_mutex);
+  int result = SASL_OK;
+  if (pni_cyrus_config_dir) {
+    result = sasl_set_path(SASL_PATH_TYPE_CONFIG, pni_cyrus_config_dir);
+  }
+  if (result==SASL_OK) {
+    result = sasl_client_init(NULL);
+  }
+  pni_cyrus_client_started = true;
+  pni_cyrus_client_init_rc = result;
+  pthread_mutex_unlock(&pni_cyrus_mutex);
+}
+
+static int pni_cyrus_server_init_rc = SASL_OK;
+static void pni_cyrus_server_once(void) {
+  pthread_mutex_lock(&pni_cyrus_mutex);
+  int result = SASL_OK;
+  if (pni_cyrus_config_dir) {
+    result = sasl_set_path(SASL_PATH_TYPE_CONFIG, pni_cyrus_config_dir);
+  }
+  if (result==SASL_OK) {
+    result = sasl_server_init(NULL, pni_cyrus_config_name);
+  }
+  pni_cyrus_server_started = true;
+  pni_cyrus_server_init_rc = result;
+  pthread_mutex_unlock(&pni_cyrus_mutex);
+}
+
+static pthread_once_t pni_cyrus_client_init = PTHREAD_ONCE_INIT;
+static void pni_cyrus_client_start(void) {
+    pthread_once(&pni_cyrus_client_init, pni_cyrus_client_once);
+}
+static pthread_once_t pni_cyrus_server_init = PTHREAD_ONCE_INIT;
+static void pni_cyrus_server_start(void) {
+  pthread_once(&pni_cyrus_server_init, pni_cyrus_server_once);
+}
+
 bool pni_init_client(pn_transport_t* transport) {
   pni_sasl_t *sasl = transport->sasl;
   int result;
   sasl_conn_t *cyrus_conn = NULL;
   do {
     if (sasl->config_dir) {
-      result = sasl_set_path(SASL_PATH_TYPE_CONFIG, sasl->config_dir);
-      if (result!=SASL_OK) break;
+      pni_cyrus_config_dir = sasl->config_dir;
     }
 
-    result = sasl_client_init(NULL);
+    pni_cyrus_client_start();
+    result = pni_cyrus_client_init_rc;
     if (result!=SASL_OK) break;
 
     const sasl_callback_t *callbacks = sasl->username ? sasl->password ? pni_user_password_callbacks : pni_user_callbacks : NULL;
@@ -246,11 +302,15 @@ bool pni_init_server(pn_transport_t* transport)
   sasl_conn_t *cyrus_conn = NULL;
   do {
     if (sasl->config_dir) {
-        result = sasl_set_path(SASL_PATH_TYPE_CONFIG, sasl->config_dir);
-        if (result!=SASL_OK) break;
+      pni_cyrus_config_dir = sasl->config_dir;
+    }
+
+    if (sasl->config_name) {
+      pni_cyrus_config_name = sasl->config_name;
     }
 
-    result = sasl_server_init(NULL, sasl->config_name ? sasl->config_name : "proton-server");
+    pni_cyrus_server_start();
+    result = pni_cyrus_server_init_rc;
     if (result!=SASL_OK) break;
 
     result = sasl_server_new(amqp_service, NULL, NULL, NULL, NULL, NULL, 0, &cyrus_conn);
@@ -456,11 +516,6 @@ void pni_sasl_impl_free(pn_transport_t *transport)
     sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
     sasl_dispose(&cyrus_conn);
     transport->sasl->impl_context = cyrus_conn;
-    if (transport->sasl->client) {
-        sasl_client_done();
-    } else {
-        sasl_server_done();
-    }
 }
 
 bool pn_sasl_extended(void)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org