summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2016-07-27 23:32:28 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2016-07-27 23:34:56 +0200
commit9c0187166c2ac045d9d886d60ebe7bddbe83e774 (patch)
tree01dd0cc41ae48b49fc8b2a72d44fc452390c2bce
parent75ba6fc573de5d0fec616dbbc35d01b1cb3ccdbf (diff)
downloadgnutls-9c0187166c2ac045d9d886d60ebe7bddbe83e774.tar.gz
gnutls_global_init/deinit: don't use any locking during constructor
This ensures that there is no deadlock on unexpected errors, such as missing symbols (e.g., on lazy linking). Reported by Ludovic Courtès.
-rw-r--r--lib/global.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/lib/global.c b/lib/global.c
index 535bb19896..d75cea8330 100644
--- a/lib/global.c
+++ b/lib/global.c
@@ -79,6 +79,9 @@ gnutls_log_func _gnutls_log_func = NULL;
gnutls_audit_log_func _gnutls_audit_log_func = NULL;
int _gnutls_log_level = 0; /* default log level */
+static int _gnutls_global_init(unsigned constructor);
+static void _gnutls_global_deinit(unsigned destructor);
+
static void default_log_func(int level, const char* str)
{
fprintf(stderr, "gnutls[%d]: %s", level, str);
@@ -217,11 +220,18 @@ static int _gnutls_init_ret = 0;
**/
int gnutls_global_init(void)
{
+ return _gnutls_global_init(0);
+}
+
+static int _gnutls_global_init(unsigned constructor)
+{
int ret = 0, res;
int level;
const char* e;
-
- GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex);
+
+ if (!constructor) {
+ GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex);
+ }
_gnutls_init++;
if (_gnutls_init > 1) {
@@ -379,13 +389,17 @@ int gnutls_global_init(void)
out:
_gnutls_init_ret = ret;
- GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
+ if (!constructor) {
+ GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
+ }
return ret;
}
static void _gnutls_global_deinit(unsigned destructor)
{
- GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex);
+ if (!destructor) {
+ GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex);
+ }
if (_gnutls_init == 1) {
_gnutls_init = 0;
@@ -431,7 +445,9 @@ static void _gnutls_global_deinit(unsigned destructor)
}
fail:
- GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
+ if (!destructor) {
+ GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex);
+ }
}
/**
@@ -485,7 +501,7 @@ const char *e;
return;
}
- ret = gnutls_global_init();
+ ret = _gnutls_global_init(1);
if (ret < 0) {
fprintf(stderr, "Error in GnuTLS initialization: %s\n", gnutls_strerror(ret));
_gnutls_switch_lib_state(LIB_STATE_ERROR);