2 // Copyright The OpenTelemetry Authors
3 // SPDX-License-Identifier: Apache-2.0
5 #include "src/common/random.h"
6 #include "src/common/platform/fork.h"
11 OPENTELEMETRY_BEGIN_NAMESPACE
16 // Wraps a thread_local random number generator, but adds a fork handler so that
17 // the generator will be correctly seeded after forking.
19 // See https://stackoverflow.com/q/51882689/4447365 and
20 // https://github.com/opentracing-contrib/nginx-opentracing/issues/52
23 class TlsRandomNumberGenerator
26 TlsRandomNumberGenerator() noexcept
29 platform::AtFork(nullptr, nullptr, OnFork
);
32 static FastRandomNumberGenerator
&engine() noexcept
{ return engine_
; }
35 static thread_local FastRandomNumberGenerator engine_
;
37 static void OnFork() noexcept
{ Seed(); }
39 static void Seed() noexcept
41 std::random_device random_device
;
42 std::seed_seq seed_seq
{random_device(), random_device(), random_device(), random_device()};
43 engine_
.seed(seed_seq
);
47 thread_local FastRandomNumberGenerator
TlsRandomNumberGenerator::engine_
{};
50 FastRandomNumberGenerator
&Random::GetRandomNumberGenerator() noexcept
52 static thread_local TlsRandomNumberGenerator random_number_generator
{};
53 return TlsRandomNumberGenerator::engine();
56 uint64_t Random::GenerateRandom64() noexcept
58 return GetRandomNumberGenerator()();
61 void Random::GenerateRandomBuffer(opentelemetry::nostd::span
<uint8_t> buffer
) noexcept
63 auto buf_size
= buffer
.size();
65 for (size_t i
= 0; i
< buf_size
; i
+= sizeof(uint64_t))
67 uint64_t value
= GenerateRandom64();
68 if (i
+ sizeof(uint64_t) <= buf_size
)
70 memcpy(&buffer
[i
], &value
, sizeof(uint64_t));
74 memcpy(&buffer
[i
], &value
, buf_size
- i
);
80 OPENTELEMETRY_END_NAMESPACE