From 21069c230b9df9e27beb73378f0fd15040435abc Mon Sep 17 00:00:00 2001 From: Dominic Prittie Date: Sat, 21 Aug 2021 09:32:45 +0100 Subject: [PATCH 1/3] add test for rand.NewSource concurrent usage --- nrpe_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nrpe_test.go b/nrpe_test.go index a59c91c..d6af0c2 100644 --- a/nrpe_test.go +++ b/nrpe_test.go @@ -9,6 +9,7 @@ import ( "bytes" "fmt" "strings" + "sync" "testing" "time" "unsafe" @@ -217,6 +218,21 @@ func TestClientServerTimeoutClient(t *testing.T) { <-c } +func TestRandSource(t *testing.T) { + const c = 1000000 + var wg sync.WaitGroup + wg.Add(c) + + for i := 0; i < c; i++ { + go func(i int) { + defer wg.Done() + randSource.Seed(0) + randSource.Uint32() + }(i) + } + wg.Wait() +} + func TestBufferRandomizer(t *testing.T) { randSource.Seed(0) From 5449aef2ceead892a39a085a96677c7db46ea027 Mon Sep 17 00:00:00 2001 From: Dominic Prittie Date: Fri, 20 Aug 2021 09:42:18 +0100 Subject: [PATCH 2/3] make safe for concurrent use --- nrpe.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/nrpe.go b/nrpe.go index 5b94ad9..1a26707 100644 --- a/nrpe.go +++ b/nrpe.go @@ -13,13 +13,31 @@ import ( "math/rand" "net" "strings" + "sync" "time" "unsafe" ) var crc32Table []uint32 -var randSource *rand.Rand +type syncedRand struct { + ra *rand.Rand + mu *sync.Mutex +} + +func (r *syncedRand) Uint32() uint32 { + r.mu.Lock() + defer r.mu.Unlock() + return r.ra.Uint32() +} + +func (r *syncedRand) Seed(seed int64) { + r.mu.Lock() + r.ra.Seed(seed) + r.mu.Unlock() +} + +var randSource *syncedRand const ( maxPacketDataLength = 1024 @@ -86,7 +104,9 @@ func init() { crc32Table[i] = crc } - randSource = rand.New(rand.NewSource(time.Now().UnixNano())) + // rand.NewSource returns a new pseudo-random Source seeded with the given value. + // Unlike the default Source used by top-level functions, this source is not safe for concurrent use by multiple goroutines. + randSource = &syncedRand{rand.New(rand.NewSource(time.Now().UnixNano())), &sync.Mutex{}} } //Builds crc32 from the given input From e8e231e08041c3847a762c4e51d8766eb64c5073 Mon Sep 17 00:00:00 2001 From: Dominic Prittie Date: Sat, 21 Aug 2021 13:11:22 +0100 Subject: [PATCH 3/3] remove test, it is not deterministic This reverts commit 21069c230b9df9e27beb73378f0fd15040435abc. --- nrpe_test.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/nrpe_test.go b/nrpe_test.go index d6af0c2..a59c91c 100644 --- a/nrpe_test.go +++ b/nrpe_test.go @@ -9,7 +9,6 @@ import ( "bytes" "fmt" "strings" - "sync" "testing" "time" "unsafe" @@ -218,21 +217,6 @@ func TestClientServerTimeoutClient(t *testing.T) { <-c } -func TestRandSource(t *testing.T) { - const c = 1000000 - var wg sync.WaitGroup - wg.Add(c) - - for i := 0; i < c; i++ { - go func(i int) { - defer wg.Done() - randSource.Seed(0) - randSource.Uint32() - }(i) - } - wg.Wait() -} - func TestBufferRandomizer(t *testing.T) { randSource.Seed(0)