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