diff --git a/zipkin/src/utility.cc b/zipkin/src/utility.cc index 2a7e6dd..613d16e 100644 --- a/zipkin/src/utility.cc +++ b/zipkin/src/utility.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -16,11 +17,34 @@ #include namespace zipkin { -uint64_t RandomUtil::generateId() { - static thread_local randutils::mt19937_64_rng rand_source; - return rand_source.engine()(); +// Wrapper for a seeded random number generator that works with forking. +// +// See https://stackoverflow.com/q/51882689/4447365 and +// https://github.com/opentracing-contrib/nginx-opentracing/issues/52 +namespace { +class TlsRandomNumberGenerator { +public: + TlsRandomNumberGenerator() { pthread_atfork(nullptr, nullptr, onFork); } + + static std::mt19937_64 &engine() { return base_generator_.engine(); } + +private: + static thread_local randutils::mt19937_64_rng base_generator_; + + static void onFork() { base_generator_.seed(); } +}; + +thread_local randutils::mt19937_64_rng + TlsRandomNumberGenerator::base_generator_; +} // namespace + +std::mt19937_64 &getTlsRandomEngine() { + static TlsRandomNumberGenerator rng; + return TlsRandomNumberGenerator::engine(); } +uint64_t RandomUtil::generateId() { return getTlsRandomEngine()(); } + bool StringUtil::atoul(const char *str, uint64_t &out, int base) { if (strlen(str) == 0) { return false; diff --git a/zipkin_opentracing/src/sampling.cc b/zipkin_opentracing/src/sampling.cc index fe7e3dc..42623ee 100644 --- a/zipkin_opentracing/src/sampling.cc +++ b/zipkin_opentracing/src/sampling.cc @@ -3,9 +3,10 @@ #include namespace zipkin { +std::mt19937_64 &getTlsRandomEngine(); + bool ProbabilisticSampler::ShouldSample() { - static thread_local randutils::mt19937_rng rng; std::bernoulli_distribution dist(sample_rate_); - return dist(rng.engine()); + return dist(getTlsRandomEngine()); } } // namespace zipkin