Add mutexes to make OpenSSL thread safe
This commit is contained in:
parent
49cbe600f9
commit
62ea4ae9c3
1 changed files with 69 additions and 0 deletions
|
|
@ -7,6 +7,16 @@
|
||||||
#include <fc/io/raw.hpp>
|
#include <fc/io/raw.hpp>
|
||||||
|
|
||||||
#include <fc/log/logger.hpp>
|
#include <fc/log/logger.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <openssl/opensslconf.h>
|
||||||
|
#ifndef OPENSSL_THREADS
|
||||||
|
# error "OpenSSL must be configured to support threads"
|
||||||
|
#endif
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
||||||
|
|
@ -365,4 +375,63 @@ std::vector<char> aes_load( const fc::path& file, const fc::sha512& key )
|
||||||
return aes_decrypt( key, cipher );
|
return aes_decrypt( key, cipher );
|
||||||
} FC_RETHROW_EXCEPTIONS( warn, "", ("file",file) ) }
|
} FC_RETHROW_EXCEPTIONS( warn, "", ("file",file) ) }
|
||||||
|
|
||||||
|
/* This stuff has to go somewhere, I guess this is as good a place as any...
|
||||||
|
OpenSSL isn't thread-safe unless you give it access to some mutexes,
|
||||||
|
so the CRYPTO_set_id_callback() function needs to be called before there's any
|
||||||
|
chance of OpenSSL being accessed from multiple threads.
|
||||||
|
*/
|
||||||
|
struct openssl_thread_config
|
||||||
|
{
|
||||||
|
static boost::mutex* openssl_mutexes;
|
||||||
|
static unsigned long get_thread_id();
|
||||||
|
static void locking_callback(int mode, int type, const char *file, int line);
|
||||||
|
openssl_thread_config();
|
||||||
|
~openssl_thread_config();
|
||||||
|
};
|
||||||
|
openssl_thread_config openssl_thread_config_manager;
|
||||||
|
|
||||||
|
boost::mutex* openssl_thread_config::openssl_mutexes = nullptr;
|
||||||
|
|
||||||
|
unsigned long openssl_thread_config::get_thread_id()
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return (unsigned long)::GetCurrentThreadId();
|
||||||
|
#else
|
||||||
|
return (unsigned long)(&fc::thread::current()); // TODO: should expose boost thread id
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void openssl_thread_config::locking_callback(int mode, int type, const char *file, int line)
|
||||||
|
{
|
||||||
|
if (mode & CRYPTO_LOCK)
|
||||||
|
openssl_mutexes[type].lock();
|
||||||
|
else
|
||||||
|
openssl_mutexes[type].unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning: Things get complicated if third-party libraries also try to install their their own
|
||||||
|
// OpenSSL thread functions. Right now, we don't install our own handlers if another library has
|
||||||
|
// installed them before us which is a partial solution, but you'd really need to evaluate
|
||||||
|
// each library that does this to make sure they will play nice.
|
||||||
|
openssl_thread_config::openssl_thread_config()
|
||||||
|
{
|
||||||
|
if (CRYPTO_get_id_callback() == NULL &&
|
||||||
|
CRYPTO_get_locking_callback() == NULL)
|
||||||
|
{
|
||||||
|
openssl_mutexes = new boost::mutex[CRYPTO_num_locks()];
|
||||||
|
CRYPTO_set_id_callback(&get_thread_id);
|
||||||
|
CRYPTO_set_locking_callback(&locking_callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
openssl_thread_config::~openssl_thread_config()
|
||||||
|
{
|
||||||
|
if (CRYPTO_get_id_callback() == &get_thread_id)
|
||||||
|
{
|
||||||
|
CRYPTO_set_id_callback(NULL);
|
||||||
|
CRYPTO_set_locking_callback(NULL);
|
||||||
|
delete[] openssl_mutexes;
|
||||||
|
openssl_mutexes = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fc
|
} // namespace fc
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue