From a67173ef634f5fd3db387c34fd56aabb7a045c50 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 8 Jan 2020 14:46:14 +0000 Subject: [PATCH 1/3] make libc dependency optional (fork protection requires std) --- CHANGELOG.md | 3 +++ Cargo.toml | 4 ++-- src/rngs/adapter/reseeding.rs | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57bb3614ff8..8a905435f30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update. - The `Bernoulli` distribution constructors now reports an error on NaN and on `denominator == 0`. (#925) +### Changes +- Unix: make libc dependency optional; only use fork protection with std feature (#928) + ### Additions - Implement `std::error::Error` for `BernoulliError` (#919) diff --git a/Cargo.toml b/Cargo.toml index e6af38d6344..03d5e35afca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ nightly = ["simd_support"] # enables all features requiring nightly rust serde1 = [] # does nothing, deprecated # Optional dependencies: -std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom"] +std = ["rand_core/std", "rand_chacha/std", "alloc", "getrandom", "libc"] alloc = ["rand_core/alloc"] # enables Vec and Box support (without std) # re-export optional WASM dependencies to avoid breakage: # Warning: wasm-bindgen and stdweb features will be removed in rand 0.8; @@ -68,7 +68,7 @@ features = ["into_bits"] [target.'cfg(unix)'.dependencies] # Used for fork protection (reseeding.rs) -libc = { version = "0.2.22", default-features = false } +libc = { version = "0.2.22", optional = true, default-features = false } # Emscripten does not support 128-bit integers, which are used by ChaCha code. # We work around this by using a different RNG. diff --git a/src/rngs/adapter/reseeding.rs b/src/rngs/adapter/reseeding.rs index f7a694f2211..bd8abd3eca9 100644 --- a/src/rngs/adapter/reseeding.rs +++ b/src/rngs/adapter/reseeding.rs @@ -279,7 +279,7 @@ where } -#[cfg(all(unix, not(target_os = "emscripten")))] +#[cfg(all(unix, feature = "std", not(target_os = "emscripten")))] mod fork { use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; #[allow(deprecated)] // Required for compatibility with Rust < 1.24. @@ -321,7 +321,7 @@ mod fork { } } -#[cfg(not(all(unix, not(target_os = "emscripten"))))] +#[cfg(not(all(unix, feature = "std", not(target_os = "emscripten"))))] mod fork { pub fn get_fork_counter() -> usize { 0 From ae3a416ecc5333a02557f6b9b29e88bee50640a0 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 8 Jan 2020 14:52:55 +0000 Subject: [PATCH 2/3] Fix #911: use Once instead of AtomicBool --- CHANGELOG.md | 1 + src/rngs/adapter/reseeding.rs | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a905435f30..3ec7462c963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update. ### Fixes - The `Bernoulli` distribution constructors now reports an error on NaN and on `denominator == 0`. (#925) +- Use `std::sync::Once` to register fork handler, avoiding possible atomicity violation (#928) ### Changes - Unix: make libc dependency optional; only use fork protection with std feature (#928) diff --git a/src/rngs/adapter/reseeding.rs b/src/rngs/adapter/reseeding.rs index bd8abd3eca9..42cc36d77e9 100644 --- a/src/rngs/adapter/reseeding.rs +++ b/src/rngs/adapter/reseeding.rs @@ -281,9 +281,10 @@ where #[cfg(all(unix, feature = "std", not(target_os = "emscripten")))] mod fork { - use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + use core::sync::atomic::{AtomicUsize, Ordering}; #[allow(deprecated)] // Required for compatibility with Rust < 1.24. - use core::sync::atomic::{ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT}; + use core::sync::atomic::{ATOMIC_USIZE_INIT}; + use std::sync::Once; // Fork protection // @@ -304,9 +305,6 @@ mod fork { RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed) } - #[allow(deprecated)] - static FORK_HANDLER_REGISTERED: AtomicBool = ATOMIC_BOOL_INIT; - extern "C" fn fork_handler() { // Note: fetch_add is defined to wrap on overflow // (which is what we want). @@ -314,10 +312,10 @@ mod fork { } pub fn register_fork_handler() { - if !FORK_HANDLER_REGISTERED.load(Ordering::Relaxed) { - unsafe { libc::pthread_atfork(None, None, Some(fork_handler)) }; - FORK_HANDLER_REGISTERED.store(true, Ordering::Relaxed); - } + static REGISTER: Once = Once::new(); + REGISTER.call_once(|| unsafe { + libc::pthread_atfork(None, None, Some(fork_handler)); + }); } } From ae4683cec7b637854ab5193b08dd78478942da81 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 8 Jan 2020 14:57:55 +0000 Subject: [PATCH 3/3] Remove use of deprecated ATOMIC_USIZE_INIT --- src/rngs/adapter/reseeding.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/rngs/adapter/reseeding.rs b/src/rngs/adapter/reseeding.rs index 42cc36d77e9..5460e3431f9 100644 --- a/src/rngs/adapter/reseeding.rs +++ b/src/rngs/adapter/reseeding.rs @@ -282,8 +282,6 @@ where #[cfg(all(unix, feature = "std", not(target_os = "emscripten")))] mod fork { use core::sync::atomic::{AtomicUsize, Ordering}; - #[allow(deprecated)] // Required for compatibility with Rust < 1.24. - use core::sync::atomic::{ATOMIC_USIZE_INIT}; use std::sync::Once; // Fork protection @@ -298,8 +296,7 @@ mod fork { // don't update `fork_counter`, so a reseed is attempted as soon as // possible. - #[allow(deprecated)] - static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = AtomicUsize::new(0); pub fn get_fork_counter() -> usize { RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed)