Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions 3rd_party/randutils/include/lightstep/randutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,13 @@ class auto_seeded : public SeedSeq {
return *this;
}

auto_seeded(default_seeds seeds)
auto_seeded(default_seeds seeds) noexcept
: SeedSeq(seeds.begin(), seeds.end())
{
// Nothing else to do
}

auto_seeded()
auto_seeded() noexcept
: auto_seeded(local_entropy())
{
// Nothing else to do
Expand Down Expand Up @@ -650,7 +650,7 @@ class random_generator {
public:
template <typename Seeding = default_seed_type,
typename... Params>
random_generator(Seeding&& seeding = default_seed_type{})
random_generator(Seeding&& seeding = default_seed_type{}) noexcept
: engine_{seed_seq_cast(std::forward<Seeding>(seeding))}
{
// Nothing (else) to do
Expand All @@ -662,7 +662,7 @@ class random_generator {
// https://llvm.org/bugs/show_bug.cgi?id=23029
template <typename Seeding,
typename... Params>
random_generator(Seeding&& seeding, Params&&... params)
random_generator(Seeding&& seeding, Params&&... params) noexcept
: engine_{seed_seq_cast(std::forward<Seeding>(seeding)),
std::forward<Params>(params)...}
{
Expand All @@ -671,7 +671,7 @@ class random_generator {

template <typename Seeding = default_seed_type,
typename... Params>
void seed(Seeding&& seeding = default_seed_type{})
void seed(Seeding&& seeding = default_seed_type{}) noexcept
{
engine_.seed(seed_seq_cast(seeding));
}
Expand Down
34 changes: 31 additions & 3 deletions src/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
#include <lightstep/randutils.h>
#include <opentracing/string_view.h>
#include <opentracing/value.h>
#include "lightstep-tracer-common/collector.pb.h"

#include <unistd.h>
#include <cmath>
#include <iomanip>
#include <random>
#include <sstream>
#include <stdexcept>
#include "lightstep-tracer-common/collector.pb.h"

#include <pthread.h>

namespace lightstep {
//------------------------------------------------------------------------------
Expand All @@ -25,12 +28,37 @@ google::protobuf::Timestamp ToTimestamp(
return ts;
}

//------------------------------------------------------------------------------
// TlsRandomNumberGenerator
//------------------------------------------------------------------------------
// Wraps a thread_local random number generator, but adds a fork handler so that
// the generator will be correctly seeded after 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 lightstep::randutils::mt19937_64_rng base_generator_;

static void OnFork() { base_generator_.seed(); }
};

thread_local lightstep::randutils::mt19937_64_rng
TlsRandomNumberGenerator::base_generator_{};
} // namespace

//------------------------------------------------------------------------------
// GenerateId
//------------------------------------------------------------------------------
uint64_t GenerateId() {
static thread_local lightstep::randutils::mt19937_64_rng rand_source{};
return rand_source.engine()();
static TlsRandomNumberGenerator random_number_generator;
return TlsRandomNumberGenerator::engine()();
}

//------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ _lightstep_test(tracer_test tracer_test.cpp
utility.cpp)
_lightstep_test(utility_test utility_test.cpp)
_lightstep_test(logger_test logger_test.cpp)
_lightstep_test(fork_id_test fork_id_test.cpp)
_lightstep_test(propagation_test propagation_test.cpp)
_lightstep_test(auto_recorder_test auto_recorder_test.cpp
utility.cpp
Expand Down
42 changes: 42 additions & 0 deletions test/fork_id_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Verifies that IDs don't clash after forking the process.
//
// See https://github.com/opentracing-contrib/nginx-opentracing/issues/52
#include "../src/utility.h"

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
using namespace lightstep;

static uint64_t* child_id;

int main() {
GenerateId();

// Set up shared memory to communicate between parent and child processes.
//
// See https://stackoverflow.com/a/13274800/4447365
child_id = static_cast<uint64_t*>(mmap(nullptr, sizeof(*child_id),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0));
*child_id = 0;
if (fork() == 0) {
*child_id = GenerateId();
exit(EXIT_SUCCESS);
} else {
wait(nullptr);
auto parent_id = GenerateId();
auto child_id_copy = *child_id;
munmap(static_cast<void*>(child_id), sizeof(*child_id));
if (parent_id == child_id_copy) {
std::cerr << "Child and parent ids are the same value " << parent_id
<< "\n";
return -1;
}
}
return 0;
}