diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2016-07-27 23:32:28 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2016-07-27 23:34:56 +0200 |
commit | 9c0187166c2ac045d9d886d60ebe7bddbe83e774 (patch) | |
tree | 01dd0cc41ae48b49fc8b2a72d44fc452390c2bce /lib/global.c | |
parent | 75ba6fc573de5d0fec616dbbc35d01b1cb3ccdbf (diff) | |
download | gnutls-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.c | 28 |
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); |