From 3d63a68dd065c6bed8dbebfb2e48d6b9db2888a8 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 28 Apr 2019 15:13:30 -0700 Subject: [PATCH] Make builtin_random thread safe --- src/builtin_random.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/builtin_random.cpp b/src/builtin_random.cpp index 617082e51..e20f22718 100644 --- a/src/builtin_random.cpp +++ b/src/builtin_random.cpp @@ -15,6 +15,17 @@ #include "io.h" #include "wutil.h" // IWYU pragma: keep +/// \return a random-seeded engine. +static std::minstd_rand get_seeded_engine() { + std::minstd_rand engine; + // seed engine with 2*32 bits of random data + // for the 64 bits of internal state of minstd_rand + std::random_device rd; + std::seed_seq seed{rd(), rd()}; + engine.seed(seed); + return engine; +} + /// The random builtin generates random numbers. int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wchar_t *cmd = argv[0]; @@ -30,16 +41,10 @@ int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) { return STATUS_CMD_OK; } - static bool seeded = false; - static std::minstd_rand engine; - if (!seeded) { - // seed engine with 2*32 bits of random data - // for the 64 bits of internal state of minstd_rand - std::random_device rd; - std::seed_seq seed{rd(), rd()}; - engine.seed(seed); - seeded = true; - } + // We have a single engine which we lazily seed. Lock it here. + static owning_lock s_engine{get_seeded_engine()}; + auto engine_lock = s_engine.acquire(); + std::minstd_rand &engine = *engine_lock; int arg_count = argc - optind; long long start, end;