Commit fe6b51ae40313036436f81d4e87d232691cdacac

Carlos Martín Nieto 2014-11-01T10:45:33

ssl: separate locking init from general init Extract the lock-setting functions into their own, as we cannot assume that it's ok for us to set this unconditionally.

diff --git a/include/git2/threads.h b/include/git2/threads.h
index 11f8972..6b42870 100644
--- a/include/git2/threads.h
+++ b/include/git2/threads.h
@@ -44,6 +44,22 @@ GIT_EXTERN(int) git_threads_init(void);
  */
 GIT_EXTERN(void) git_threads_shutdown(void);
 
+/**
+ * Initialize the OpenSSL locks
+ *
+ * OpenSSL requires the application to determine how it performs
+ * locking. This is a convenience function which libgit2 provides for
+ * allocating and initializing the locks as well as setting the
+ * locking function to use the system's native locking functions.
+ *
+ * The locking function will be cleared and the memory will be freed
+ * when you call git_threads_sutdown().
+ *
+ * @return 0 on success, -1 if there are errors or if libgit2 was not
+ * built with OpenSSL and threading support.
+ */
+GIT_EXTERN(int) git_openssl_set_locking(void);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/global.c b/src/global.c
index 2435b56..3e721ee 100644
--- a/src/global.c
+++ b/src/global.c
@@ -64,7 +64,7 @@ void openssl_locking_function(int mode, int n, const char *file, int line)
 	}
 }
 
-static void shutdown_ssl(void)
+static void shutdown_ssl_locking(void)
 {
 	CRYPTO_set_locking_callback(NULL);
 	git__free(openssl_locks);
@@ -96,30 +96,35 @@ static void init_ssl(void)
 		SSL_CTX_free(git__ssl_ctx);
 		git__ssl_ctx = NULL;
 	}
+#endif
+}
 
+int git_openssl_set_locking(void)
+{
+#ifdef GIT_SSL
 # ifdef GIT_THREADS
-	{
-		int num_locks, i;
-
-		num_locks = CRYPTO_num_locks();
-		openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
-		if (openssl_locks == NULL) {
-			SSL_CTX_free(git__ssl_ctx);
-			git__ssl_ctx = NULL;
-		}
+	int num_locks, i;
 
-		for (i = 0; i < num_locks; i++) {
-			if (git_mutex_init(&openssl_locks[i]) != 0) {
-				SSL_CTX_free(git__ssl_ctx);
-				git__ssl_ctx = NULL;
-			}
-		}
+	num_locks = CRYPTO_num_locks();
+	openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
+	GITERR_CHECK_ALLOC(openssl_locks);
 
-		CRYPTO_set_locking_callback(openssl_locking_function);
+	for (i = 0; i < num_locks; i++) {
+		if (git_mutex_init(&openssl_locks[i]) != 0) {
+			giterr_set(GITERR_SSL, "failed to initialize openssl locks");
+			return -1;
+		}
 	}
 
-	git__on_shutdown(shutdown_ssl);
+	CRYPTO_set_locking_callback(openssl_locking_function);
+	git__on_shutdown(shutdown_ssl_locking);
+	return 0;
+# else
+	giterr_set(GITERR_THREAD, "libgit2 as not built with threads");
+	return -1;
 # endif
+	giterr_set(GITERR_SSL, "libgit2 was not built with OpenSSL support");
+	return -1;
 #endif
 }