From 607e323f3791f3701e61b47e74280deb9aa26a22 Mon Sep 17 00:00:00 2001 From: Subodh Iyengar Date: Tue, 25 Nov 2014 13:07:16 -0800 Subject: [PATCH] Make SSLContext's exit() handling more graceful Summary: Some platforms that SSLContext run on call exit() despite best practices. This cause the static structures to be destructed and cause race conditions and crashes. This new's the static structures so that they won't be destructed on exit() Test Plan: Unit tests Reviewed By: seanc@fb.com Subscribers: trunkagent, ssl-diffs@, seanc, njormrod, folly-diffs@ FB internal diff: D1702186 Tasks: 5572637 Signature: t1:1702186:1416941649:c5bdfd8cc604fc3618f51bdb8b910b5b2cf350ad --- folly/io/async/SSLContext.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/folly/io/async/SSLContext.cpp b/folly/io/async/SSLContext.cpp index 106974b0..80d414b0 100644 --- a/folly/io/async/SSLContext.cpp +++ b/folly/io/async/SSLContext.cpp @@ -538,14 +538,31 @@ struct SSLLock { std::mutex mutex; }; -static std::map lockTypes; -static std::unique_ptr locks; +// Statics are unsafe in environments that call exit(). +// If one thread calls exit() while another thread is +// references a member of SSLContext, bad things can happen. +// SSLContext runs in such environments. +// Instead of declaring a static member we "new" the static +// member so that it won't be destructed on exit(). +static std::map* lockTypesInst = + new std::map(); + +static std::unique_ptr* locksInst = + new std::unique_ptr(); + +static std::unique_ptr& locks() { + return *locksInst; +} + +static std::map& lockTypes() { + return *lockTypesInst; +} static void callbackLocking(int mode, int n, const char*, int) { if (mode & CRYPTO_LOCK) { - locks[n].lock(); + locks()[n].lock(); } else { - locks[n].unlock(); + locks()[n].unlock(); } } @@ -580,7 +597,7 @@ static void dyn_destroy(struct CRYPTO_dynlock_value* lock, const char*, int) { } void SSLContext::setSSLLockTypes(std::map inLockTypes) { - lockTypes = inLockTypes; + lockTypes() = inLockTypes; } void SSLContext::initializeOpenSSL() { @@ -596,9 +613,9 @@ void SSLContext::initializeOpenSSLLocked() { SSL_load_error_strings(); ERR_load_crypto_strings(); // static locking - locks.reset(new SSLLock[::CRYPTO_num_locks()]); - for (auto it: lockTypes) { - locks[it.first].lockType = it.second; + locks().reset(new SSLLock[::CRYPTO_num_locks()]); + for (auto it: lockTypes()) { + locks()[it.first].lockType = it.second; } CRYPTO_set_id_callback(callbackThreadID); CRYPTO_set_locking_callback(callbackLocking); @@ -633,7 +650,7 @@ void SSLContext::cleanupOpenSSLLocked() { ERR_free_strings(); EVP_cleanup(); ERR_remove_state(0); - locks.reset(); + locks().reset(); initialized_ = false; } -- 2.34.1