From aa7818e1d342ffbed3588f6bdece621b119debec Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Wed, 16 Mar 2022 09:24:58 -0700 Subject: [PATCH] Update to avoid pseudo-random number (#5225) * Update to avoid pseudo-random number This PR update the usage of rand so that non-global seed is used. Signed-off-by: Yong Tang * Add concurrency-safe random source See https://stackoverflow.com/questions/48958886/how-to-create-a-thread-safe-rand-source Signed-off-by: Yong Tang --- plugin/forward/policy.go | 10 +++++++--- plugin/grpc/policy.go | 10 +++++++--- plugin/loop/setup.go | 4 ++-- plugin/pkg/rand/rand.go | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 plugin/pkg/rand/rand.go diff --git a/plugin/forward/policy.go b/plugin/forward/policy.go index 2066e1316..e81e4ab91 100644 --- a/plugin/forward/policy.go +++ b/plugin/forward/policy.go @@ -1,8 +1,10 @@ package forward import ( - "math/rand" "sync/atomic" + "time" + + "github.com/coredns/coredns/plugin/pkg/rand" ) // Policy defines a policy we use for selecting upstreams. @@ -21,13 +23,13 @@ func (r *random) List(p []*Proxy) []*Proxy { case 1: return p case 2: - if rand.Int()%2 == 0 { + if rn.Int()%2 == 0 { return []*Proxy{p[1], p[0]} // swap } return p } - perms := rand.Perm(len(p)) + perms := rn.Perm(len(p)) rnd := make([]*Proxy, len(p)) for i, p1 := range perms { @@ -62,3 +64,5 @@ func (r *sequential) String() string { return "sequential" } func (r *sequential) List(p []*Proxy) []*Proxy { return p } + +var rn = rand.New(time.Now().UnixNano()) diff --git a/plugin/grpc/policy.go b/plugin/grpc/policy.go index 66351d822..686b2ebb6 100644 --- a/plugin/grpc/policy.go +++ b/plugin/grpc/policy.go @@ -1,8 +1,10 @@ package grpc import ( - "math/rand" "sync/atomic" + "time" + + "github.com/coredns/coredns/plugin/pkg/rand" ) // Policy defines a policy we use for selecting upstreams. @@ -21,13 +23,13 @@ func (r *random) List(p []*Proxy) []*Proxy { case 1: return p case 2: - if rand.Int()%2 == 0 { + if rn.Int()%2 == 0 { return []*Proxy{p[1], p[0]} // swap } return p } - perms := rand.Perm(len(p)) + perms := rn.Perm(len(p)) rnd := make([]*Proxy, len(p)) for i, p1 := range perms { @@ -62,3 +64,5 @@ func (r *sequential) String() string { return "sequential" } func (r *sequential) List(p []*Proxy) []*Proxy { return p } + +var rn = rand.New(time.Now().UnixNano()) diff --git a/plugin/loop/setup.go b/plugin/loop/setup.go index 6af7b3baa..4e076c687 100644 --- a/plugin/loop/setup.go +++ b/plugin/loop/setup.go @@ -1,7 +1,6 @@ package loop import ( - "math/rand" "net" "strconv" "time" @@ -10,6 +9,7 @@ import ( "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/pkg/dnsutil" + "github.com/coredns/coredns/plugin/pkg/rand" ) func init() { plugin.Register("loop", setup) } @@ -84,4 +84,4 @@ func qname(zone string) string { return dnsutil.Join(l1, l2, zone) } -var r = rand.New(rand.NewSource(time.Now().UnixNano())) +var r = rand.New(time.Now().UnixNano()) diff --git a/plugin/pkg/rand/rand.go b/plugin/pkg/rand/rand.go new file mode 100644 index 000000000..d2b3960b4 --- /dev/null +++ b/plugin/pkg/rand/rand.go @@ -0,0 +1,36 @@ +// Package rand is used for concurrency safe random number generator. +package rand + +import ( + "math/rand" + "sync" +) + +// Rand is used for concurrency safe random number generator. +type Rand struct { + m sync.Mutex + r *rand.Rand +} + +// New returns a new Rand from seed. +func New(seed int64) *Rand { + return &Rand{r: rand.New(rand.NewSource(seed))} +} + +// Int returns a non-negative pseudo-random int from the Source in Rand.r. +func (r *Rand) Int() int { + r.m.Lock() + v := r.r.Int() + r.m.Unlock() + return v +} + +// Perm returns, as a slice of n ints, a pseudo-random permutation of the +// integers in the half-open interval [0,n) from the Source in Rand.r. +func (r *Rand) Perm(n int) []int { + r.m.Lock() + v := r.r.Perm(n) + r.m.Unlock() + return v + +}