Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
randutil: allow pseudo rng seeding by caller
The randutil package was promoted to the x-go library because it provides helper functions needed by other projects (Pebble). The changes proposed here will be applied to snapd so that both packages are kept in sync. Feedback from canonical#17 highlighted the need for seeding of the pseudo random dependent functions to be left to the user of randutil (the crypto/rand functions are unaffected). The reason is simply that the seeding requirements differ between use cases (and projects), and it should be the responsibility of the caller to supply the seed. In addition to the requirement above, the original snapd randutil pseudo random implementation has the following side effects: (1) It is based on the Go global pseudo random provided by math/rand. This means that re-seeding affects all packages dependent on the prng, irrespective of the individual seeding requirements. For example: Calling RandomDuration() the first time would re-seed the global prng and all subsequent calls to RandomString() and RandomDuration() would use the new seed. At the same time, anyone accidentally calling rand.Seed() in any other package or imported library will reset the seed, affecting both RandomDuration() and RandomString(). (2) Access from all users are serialised by a single global lock. This is not an issue for snapd, but may not be performance optimal for all applications. This proposal does not address issue directly yet. https://qqq.ninja/blog/post/fast-threadsafe-randomness-in-go/ (3) Automatic seeding of the global prng was enabled from Go v1.20. This does not directly affect is, but introduces changes that could effect tests build on assumptions of code using the global prng. This patch makes the following changes: - RandomDuration can no longer create a panic (make this a caller decision). Code that wants to panic can still panic before calling RandomDuration if the duration is negative. Instead, always return zero (0) duration for inputs <= 0. (snapd already added caller code to explicitly avoid this in the first place) - Improve the unit testing to cover the complete range for both pseudo random functions. - Change the randutil pseudo random functions to standalone prng instances, each initialised with their own seed value. - Add a local lock to make the prng instance go-routine safe. - Supply two template seeding functions based on the previously used snapd code: SeedDatePid() SeedDatePidHostMac() - Add Reseed() method for resetting the seed during testing. Example Usage: prng := randutil.NewPseudoRand(nil) : tmpfile := prng.RandomString(12) : wait := prng.RandomDuration(time.Hour) Signed-off-by: Fred Lotter <fred.lotter@canonical.com>
- Loading branch information