-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DATA RACE: rand.NewSource is not safe for concurrent usage. #10988
Comments
Most of these were introduced by #10575 in an attempt to avoid unrelated packages interfering with each others PRNG state. I didn't read the docs carefully enough so didn't spot that this method is not concurrency-safe 😕 It seems there currently isn't an easy way to get a non-global, concurrency-safe PRNG source with the current My proposal to solved this would be use something similar to |
The godoc comment for package `math/rand` states: The default Source is safe for concurrent use by multiple goroutines, but Sources created by NewSource are not. The global source in `math/rand` would be concurrency-safe, but its state may be interfered with from unrelated packages, e.g. ``` package a func init() { math.Seed(time.Now().UnixNano() } ``` and ``` package b func init() { math.Seed(0) } ``` Depending on the package load order, the PRNG state would be predictable for all users (i.e. always seeded using the fixed value 0), including `package a`. To fix this, provide a concurrency-safe wrapper around `math/rand.Rand` in `pkg/rand` and use it to replace all existing users of `math/rand.New(rand.NewSource(...))` Fixes #10988 Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
The godoc comment for package `math/rand` states: The default Source is safe for concurrent use by multiple goroutines, but Sources created by NewSource are not. The global source in `math/rand` would be concurrency-safe, but its state may be interfered with from unrelated packages, e.g. ``` package a func init() { math.Seed(time.Now().UnixNano() } ``` and ``` package b func init() { math.Seed(0) } ``` Depending on the package load order, the PRNG state would be predictable for all users (i.e. always seeded using the fixed value 0), including `package a`. To fix this, provide a concurrency-safe wrapper around `math/rand.Rand` in `pkg/rand` and use it to replace all existing users of `math/rand.New(rand.NewSource(...))` Fixes #10988 Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
[ upstream commit fac5dde ] Backport notes: Backported as requirement for b95650b ("etcd: Shuffle list of etcd endpoints") The godoc comment for package `math/rand` states: The default Source is safe for concurrent use by multiple goroutines, but Sources created by NewSource are not. The global source in `math/rand` would be concurrency-safe, but its state may be interfered with from unrelated packages, e.g. ``` package a func init() { math.Seed(time.Now().UnixNano() } ``` and ``` package b func init() { math.Seed(0) } ``` Depending on the package load order, the PRNG state would be predictable for all users (i.e. always seeded using the fixed value 0), including `package a`. To fix this, provide a concurrency-safe wrapper around `math/rand.Rand` in `pkg/rand` and use it to replace all existing users of `math/rand.New(rand.NewSource(...))` Fixes #10988 Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Thomas Graf <thomas@cilium.io>
[ upstream commit fac5dde ] Backport notes: Backported as requirement for b95650b ("etcd: Shuffle list of etcd endpoints") The godoc comment for package `math/rand` states: The default Source is safe for concurrent use by multiple goroutines, but Sources created by NewSource are not. The global source in `math/rand` would be concurrency-safe, but its state may be interfered with from unrelated packages, e.g. ``` package a func init() { math.Seed(time.Now().UnixNano() } ``` and ``` package b func init() { math.Seed(0) } ``` Depending on the package load order, the PRNG state would be predictable for all users (i.e. always seeded using the fixed value 0), including `package a`. To fix this, provide a concurrency-safe wrapper around `math/rand.Rand` in `pkg/rand` and use it to replace all existing users of `math/rand.New(rand.NewSource(...))` Fixes #10988 Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Thomas Graf <thomas@cilium.io>
Since Go 1.20 the top-level math/rand functions are auto-seeded by default, see https://go.dev/doc/go1.20#library and golang/go#54880. They also use the runtime's lock-free fastrand64 function when 1. Seed has not been called and 2. GODEBUG=randautoseed=0 is not used, see golang/go#49892. This allows to drop SafeRand and use the global source again. SafeRand was introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which couldn't be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. rand.Seed is deprecated since GO 1.20 and per the paragraph above the global source is seeded by default. This makes it unlikely that packages would interfere with the global PRNG state anymore and the top-level math/rand functions are safe to use again. Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.20 the top-level math/rand functions are auto-seeded by default, see https://go.dev/doc/go1.20#library and golang/go#54880. They also use the runtime's lock-free fastrand64 function when 1. Seed has not been called and 2. GODEBUG=randautoseed=0 is not used, see golang/go#49892. This allows to drop SafeRand and use the global source again. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. rand.Seed is deprecated since Go 1.20 and per the paragraph above the global source is seeded by default. This makes it unlikely that packages would interfere with the global PRNG state anymore and the top-level math/rand functions are safe to use again. Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.20 the top-level math/rand functions are auto-seeded by default, see https://go.dev/doc/go1.20#library and golang/go#54880. They also use the runtime's lock-free fastrand64 function when 1. Seed has not been called and 2. GODEBUG=randautoseed=0 is not used, see golang/go#49892. This allows to drop SafeRand and use the global source again. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. rand.Seed is deprecated since Go 1.20 and per the paragraph above the global source is seeded by default. This makes it unlikely that packages would interfere with the global PRNG state anymore and the top-level math/rand functions are safe to use again. Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.20 the top-level math/rand functions are auto-seeded by default, see https://go.dev/doc/go1.20#library and golang/go#54880. They also use the runtime's lock-free fastrand64 function when 1. Seed has not been called and 2. GODEBUG=randautoseed=0 is not used, see golang/go#49892. This allows to drop SafeRand and use the global source again. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. rand.Seed is deprecated since Go 1.20 and per the paragraph above the global source is seeded by default. This makes it unlikely that packages would interfere with the global PRNG state anymore and the top-level math/rand functions are safe to use again. Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.20 the top-level math/rand functions are auto-seeded by default, see https://go.dev/doc/go1.20#library and golang/go#54880. They also use the runtime's lock-free fastrand64 function when 1. Seed has not been called and 2. GODEBUG=randautoseed=0 is not used, see golang/go#49892. This allows to drop SafeRand and use the global source again. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. rand.Seed is deprecated since Go 1.20 and per the paragraph above the global source is seeded by default. This makes it unlikely that packages would interfere with the global PRNG state anymore and the top-level math/rand functions are safe to use again. Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.22 the Go standard library provides the math/rand/v2 package [^1]. Its global generator accessed by top-level functions is unconditionally seeded using a true random value. Moreover, the new package provides a way to construct PRNG sources which can be accessed concurrently. This allows to drop SafeRand and use the global source again where applicable. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. In some cases the global math/rand/v2 source cannot be used because unit tests rely on seeding the PRNG source to a fixed value for deterministic test runs. In these cases a math/rand/v2 source using fixed values is used, like with SafeRand before. [^1] https://go.dev/doc/go1.22#math_rand_v2 Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.22 the Go standard library provides the math/rand/v2 package[^1]. Its global generator accessed by top-level functions is unconditionally seeded using a true random value. Moreover, the new package provides a way to construct PRNG sources which can be accessed concurrently. This allows to drop SafeRand and use the global source again where applicable. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. In some cases the global math/rand/v2 source cannot be used because unit tests rely on seeding the PRNG source to a fixed value for deterministic test runs. In these cases a math/rand/v2 source using fixed values is used, like with SafeRand before. [^1]: https://go.dev/doc/go1.22#math_rand_v2 Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.22 the Go standard library provides the math/rand/v2 package[^1]. Its global generator accessed by top-level functions is unconditionally seeded using a true random value. Moreover, the new package provides a way to construct PRNG sources which can be accessed concurrently. This allows to drop SafeRand and use the global source again where applicable. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. In some cases the global math/rand/v2 source cannot be used because unit tests rely on seeding the PRNG source to a fixed value for deterministic test runs. In these cases a math/rand/v2 source using fixed values is used, like with SafeRand before. [^1]: https://go.dev/doc/go1.22#math_rand_v2 Signed-off-by: Tobias Klauser <tobias@cilium.io>
Since Go 1.22 the Go standard library provides the math/rand/v2 package[^1]. Its global generator accessed by top-level functions is unconditionally seeded using a true random value. Moreover, the new package provides a way to construct PRNG sources which can be accessed concurrently. This allows to drop SafeRand and use the global source again where applicable. SafeRand was originally introduced in commit fac5dde ("rand: add and use concurrency-safe PRNG source") to fix #10988 by providing a concurrency-safe PRNG source other than the global math/rand source which could be used at the time because it can't be interfered with from unrelated packages by means of calling rand.Seed, see #10575. In some cases the global math/rand/v2 source cannot be used because unit tests rely on seeding the PRNG source to a fixed value for deterministic test runs. In these cases a math/rand/v2 source using fixed values is used, like with SafeRand before. [^1]: https://go.dev/doc/go1.22#math_rand_v2 Signed-off-by: Tobias Klauser <tobias@cilium.io>
we have a couple usages of this function:
source 1000f70
The documentation states it's not safe for concurrent usage:
Can cause issues similar to:
The text was updated successfully, but these errors were encountered: