From 8400a1f576a31928f688a86e097371dafd09e95f Mon Sep 17 00:00:00 2001 From: Bryan Honof Date: Tue, 1 Oct 2024 21:56:47 +0200 Subject: [PATCH] fix: use portable C++ RNG I used "A Tour of C++, Third Edition" (ISBN-10 0136816487) as inspiration for the Random class. This replaces all occurrences of `rand()` and `srand()`. Co-authored-by: John Ericson --- src/libmain/shared.cc | 5 ----- src/libstore/build/derivation-goal.cc | 3 ++- src/libstore/indirect-root-store.cc | 2 +- src/libstore/indirect-root-store.hh | 3 +++ src/libstore/optimise-store.cc | 2 +- src/libstore/sqlite.cc | 3 ++- src/libutil/meson.build | 1 + src/libutil/random.hh | 28 +++++++++++++++++++++++++++ 8 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 src/libutil/random.hh diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index a224f8d92a4..5648b53f580 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -177,11 +177,6 @@ void initNix(bool loadConfig) /* Initialise the PRNG. */ struct timeval tv; gettimeofday(&tv, 0); -#ifndef _WIN32 - srandom(tv.tv_usec); -#endif - srand(tv.tv_usec); - } diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index b809e3ffe3f..db84ddbf9bf 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -17,6 +17,7 @@ #include "topo-sort.hh" #include "callback.hh" #include "local-store.hh" // TODO remove, along with remaining downcasts +#include "random.hh" #include #include @@ -803,7 +804,7 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath) tmpPath (the replacement), so we have to move it out of the way first. We'd better not be interrupted here, because if we're repairing (say) Glibc, we end up with a broken system. */ - Path oldPath = fmt("%1%.old-%2%-%3%", storePath, getpid(), rand()); + Path oldPath = fmt("%1%.old-%2%-%3%", storePath, getpid(), Random{}()); if (pathExists(storePath)) movePath(storePath, oldPath); diff --git a/src/libstore/indirect-root-store.cc b/src/libstore/indirect-root-store.cc index 844d0d6edad..744928ec970 100644 --- a/src/libstore/indirect-root-store.cc +++ b/src/libstore/indirect-root-store.cc @@ -8,7 +8,7 @@ void IndirectRootStore::makeSymlink(const Path & link, const Path & target) createDirs(dirOf(link)); /* Create the new symlink. */ - Path tempLink = fmt("%1%.tmp-%2%-%3%", link, getpid(), rand()); + Path tempLink = fmt("%1%.tmp-%2%-%3%", link, getpid(), rng()); createSymlink(target, tempLink); /* Atomically replace the old one. */ diff --git a/src/libstore/indirect-root-store.hh b/src/libstore/indirect-root-store.hh index b74ebc1eed4..2c224c39853 100644 --- a/src/libstore/indirect-root-store.hh +++ b/src/libstore/indirect-root-store.hh @@ -2,6 +2,7 @@ ///@file #include "local-fs-store.hh" +#include "random.hh" namespace nix { @@ -68,6 +69,8 @@ struct IndirectRootStore : public virtual LocalFSStore */ virtual void addIndirectRoot(const Path & path) = 0; + Random rng{}; + protected: void makeSymlink(const Path & link, const Path & target); }; diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc index 9d903f21869..0dcd01aaed4 100644 --- a/src/libstore/optimise-store.cc +++ b/src/libstore/optimise-store.cc @@ -222,7 +222,7 @@ void LocalStore::optimisePath_(Activity * act, OptimiseStats & stats, its timestamp back to 0. */ MakeReadOnly makeReadOnly(mustToggle ? dirOfPath : ""); - std::filesystem::path tempLink = fmt("%1%/.tmp-link-%2%-%3%", realStoreDir, getpid(), rand()); + std::filesystem::path tempLink = fmt("%1%/.tmp-link-%2%-%3%", realStoreDir, getpid(), rng()); try { std::filesystem::create_hard_link(linkPath, tempLink); diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc index 3175c197870..0e76401f8b2 100644 --- a/src/libstore/sqlite.cc +++ b/src/libstore/sqlite.cc @@ -3,6 +3,7 @@ #include "util.hh" #include "url.hh" #include "signals.hh" +#include "random.hh" #include @@ -258,7 +259,7 @@ void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning) is likely to fail again. */ checkInterrupt(); /* <= 0.1s */ - std::this_thread::sleep_for(std::chrono::milliseconds { rand() % 100 }); + std::this_thread::sleep_for(std::chrono::milliseconds { Random{0, 100}() }); } } diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 57b741a50a4..9f79da39092 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -248,6 +248,7 @@ headers = [config_h] + files( 'util.hh', 'variant-wrapper.hh', 'xml-writer.hh', + 'random.hh' ) if host_machine.system() == 'linux' diff --git a/src/libutil/random.hh b/src/libutil/random.hh new file mode 100644 index 00000000000..8400c8135ce --- /dev/null +++ b/src/libutil/random.hh @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +namespace nix { + +// Inspired by the book "A Tour of C++, Third Edition" (ISBN-10 0136816487) +class Random +{ +public: + Random(int low = std::numeric_limits::min(), int high = std::numeric_limits::max()) + : re(std::random_device{}()) + , dist(low, high){}; + int operator()() + { + return dist(re); + } + void seed(int s) + { + re.seed(s); + } +private: + std::default_random_engine re; + std::uniform_int_distribution dist; +}; + +} // namespace nix