summaryrefslogtreecommitdiff
path: root/lib/global.c
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 /lib/global.c
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.
Diffstat (limited to 'lib/global.c')
-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);