Commit 66a8324a authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Ensure global inits in Random are static-safe

Summary:
[Folly] Ensure global inits in Random are static-safe by using the machinery of `static` local variables.

The default mutex type used with `once_flag` is `SharedMutex`, but that mutex type is not trivially-destructible. An alternative mutex type might be trivially-destructible, such as `MicroLock`, so an alternative solution could be to use `once_flag` with `MicroLock`.

Reviewed By: ot, luciang

Differential Revision: D19207285

fbshipit-source-id: a7d817cf8521337543e3e27bc0e0e61241714ced
parent ba225d4b
...@@ -21,13 +21,13 @@ ...@@ -21,13 +21,13 @@
#include <mutex> #include <mutex>
#include <random> #include <random>
#include <folly/CppAttributes.h>
#include <folly/File.h> #include <folly/File.h>
#include <folly/FileUtil.h> #include <folly/FileUtil.h>
#include <folly/SingletonThreadLocal.h> #include <folly/SingletonThreadLocal.h>
#include <folly/ThreadLocal.h> #include <folly/ThreadLocal.h>
#include <folly/portability/SysTime.h> #include <folly/portability/SysTime.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
#include <folly/synchronization/CallOnce.h>
#include <glog/logging.h> #include <glog/logging.h>
#ifdef _MSC_VER #ifdef _MSC_VER
...@@ -40,25 +40,21 @@ namespace { ...@@ -40,25 +40,21 @@ namespace {
void readRandomDevice(void* data, size_t size) { void readRandomDevice(void* data, size_t size) {
#ifdef _MSC_VER #ifdef _MSC_VER
static folly::once_flag flag; static auto const cryptoProv = [] {
static HCRYPTPROV cryptoProv; HCRYPTPROV prov;
folly::call_once(flag, [&] {
if (!CryptAcquireContext( if (!CryptAcquireContext(
&cryptoProv, &prov, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
nullptr,
nullptr,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
if (GetLastError() == NTE_BAD_KEYSET) { if (GetLastError() == NTE_BAD_KEYSET) {
// Mostly likely cause of this is that no key container // Mostly likely cause of this is that no key container
// exists yet, so try to create one. // exists yet, so try to create one.
PCHECK(CryptAcquireContext( PCHECK(CryptAcquireContext(
&cryptoProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET)); &prov, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET));
} else { } else {
LOG(FATAL) << "Failed to acquire the default crypto context."; LOG(FATAL) << "Failed to acquire the default crypto context.";
} }
} }
}); return prov;
}();
CHECK(size <= std::numeric_limits<DWORD>::max()); CHECK(size <= std::numeric_limits<DWORD>::max());
PCHECK(CryptGenRandom(cryptoProv, (DWORD)size, (BYTE*)data)); PCHECK(CryptGenRandom(cryptoProv, (DWORD)size, (BYTE*)data));
#else #else
...@@ -73,7 +69,6 @@ void readRandomDevice(void* data, size_t size) { ...@@ -73,7 +69,6 @@ void readRandomDevice(void* data, size_t size) {
class BufferedRandomDevice { class BufferedRandomDevice {
public: public:
static once_flag flag;
static constexpr size_t kDefaultBufferSize = 128; static constexpr size_t kDefaultBufferSize = 128;
static void notifyNewGlobalEpoch() { static void notifyNewGlobalEpoch() {
...@@ -107,7 +102,6 @@ class BufferedRandomDevice { ...@@ -107,7 +102,6 @@ class BufferedRandomDevice {
unsigned char* ptr_; unsigned char* ptr_;
}; };
once_flag BufferedRandomDevice::flag;
std::atomic<size_t> BufferedRandomDevice::globalEpoch_{0}; std::atomic<size_t> BufferedRandomDevice::globalEpoch_{0};
struct RandomTag {}; struct RandomTag {};
...@@ -115,7 +109,7 @@ BufferedRandomDevice::BufferedRandomDevice(size_t bufferSize) ...@@ -115,7 +109,7 @@ BufferedRandomDevice::BufferedRandomDevice(size_t bufferSize)
: bufferSize_(bufferSize), : bufferSize_(bufferSize),
buffer_(new unsigned char[bufferSize]), buffer_(new unsigned char[bufferSize]),
ptr_(buffer_.get() + bufferSize) { // refill on first use ptr_(buffer_.get() + bufferSize) { // refill on first use
call_once(flag, [] { FOLLY_MAYBE_UNUSED static auto const init = [] {
detail::AtFork::registerHandler( detail::AtFork::registerHandler(
nullptr, nullptr,
/*prepare*/ []() { return true; }, /*prepare*/ []() { return true; },
...@@ -125,7 +119,8 @@ BufferedRandomDevice::BufferedRandomDevice(size_t bufferSize) ...@@ -125,7 +119,8 @@ BufferedRandomDevice::BufferedRandomDevice(size_t bufferSize)
// Ensure child and parent do not share same entropy pool. // Ensure child and parent do not share same entropy pool.
BufferedRandomDevice::notifyNewGlobalEpoch(); BufferedRandomDevice::notifyNewGlobalEpoch();
}); });
}); return 0;
}();
} }
void BufferedRandomDevice::getSlow(unsigned char* data, size_t size) { void BufferedRandomDevice::getSlow(unsigned char* data, size_t size) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment