Skip to content

Commit 1ba3a1c

Browse files
committed
use_file: std::sync::Mutex, dropping all libpthread use.
pthreads mutexes are not safe to move. While it is very unlikely that the mutex we create will ever be moved, we don't actively do anything to actively prevent it from being moved. (libstd, when it used/uses pthreads mutexes, would box them to prevent them from being moved.) Also, now on Linux and Android (and many other targets for which we don't use use_std), libstd uses futexes instead of pthreads mutexes. Thus using libstd's Mutex will be more efficient and avoid adding an often-otherwise-unnecessary libpthreads dependency on these targets. * Linux, Android: Futex [1]. * Haiku, Redox, NTO, AIX: pthreads [2]. * others: not using `use_file`. This will not affect our plans for *-*-linux-none, since we don't plan to use `use_file` for it. OnceLock This breaks 32-bit x86 QNX Neutrino, which doesn't have libstd because the target itself is abandoned [3]. the other QNX Neutrino targets didn't get libstd support until Rust 1.69, so this effectively raises the MSRV for them to 1.69. Otherwise, the MSRV increases to 1.63 for the above-mentioned targets, as that's when `Mutex::new()` became a `const fn`. I tried to use `Once` to avoid the MSRV increase but it doesn't support fallible initialization even in Nightly. `OnceLock` wasn't added until 1.70. On x86_64 Linux, this change removes all libpthreads dependencies: ```diff - pthread_mutex_lock - pthread_mutex_unlock ``` and adds these libstd dependencies: ```diff + std::panicking::panic_count::GLOBAL_PANIC_COUNT + std::panicking::panic_count::is_zero_slow_path + std::sys::sync::mutex::futex::Mutex::lock_contended + std::sys::sync::mutex::futex::Mutex::wake ``` as measured using `cargo asm`. [1] https://github.com/rust-lang/rust/blob/c1dba09f263cbff6170f130aa418e28bdf22bd96/library/std/src/sys/sync/mutex/mod.rs#L4-L10 [2] https://github.com/rust-lang/rust/blob/c1dba09f263cbff6170f130aa418e28bdf22bd96/library/std/src/sys/sync/mutex/mod.rs#L17-L20 [3] #453 (comment)
1 parent cdb34e3 commit 1ba3a1c

File tree

6 files changed

+12
-36
lines changed

6 files changed

+12
-36
lines changed

.clippy.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
msrv = "1.57"
1+
msrv = "1.63"

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
strategy:
4545
matrix:
4646
os: [ubuntu-22.04, windows-2022]
47-
toolchain: [nightly, beta, stable, 1.57]
47+
toolchain: [nightly, beta, stable, 1.63]
4848
# Only Test macOS on stable to reduce macOS CI jobs
4949
include:
5050
# x86_64-apple-darwin.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "getrandom"
33
version = "0.2.15" # Also update html_root_url in lib.rs when bumping this
44
edition = "2021"
5-
rust-version = "1.57" # Sync .clippy.toml, tests.yml, and README.md.
5+
rust-version = "1.63" # Sync .clippy.toml, tests.yml, and README.md.
66
authors = ["The Rand Project Developers"]
77
license = "MIT OR Apache-2.0"
88
description = "A small cross-platform library for retrieving random data from system source"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ crate features, WASM support and Custom RNGs see the
5252

5353
## Minimum Supported Rust Version
5454

55-
This crate requires Rust 1.57.0 or later.
55+
This crate requires Rust 1.63.0 or later.
5656

5757
## Platform Support
5858

src/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ impl Error {
5858
pub const NODE_ES_MODULE: Error = internal_error(14);
5959
/// Calling Windows ProcessPrng failed.
6060
pub const WINDOWS_PROCESS_PRNG: Error = internal_error(15);
61+
/// The mutex used when opening the random file was poisoned.
62+
pub const UNEXPECTED_FILE_MUTEX_POISONED: Error = internal_error(16);
6163

6264
/// Codes below this point represent OS Errors (i.e. positive i32 values).
6365
/// Codes at or above this point, but below [`Error::CUSTOM_START`] are
@@ -175,6 +177,7 @@ fn internal_desc(error: Error) -> Option<&'static str> {
175177
Error::NODE_RANDOM_FILL_SYNC => Some("Calling Node.js API crypto.randomFillSync failed"),
176178
Error::NODE_ES_MODULE => Some("Node.js ES modules are not directly supported, see https://docs.rs/getrandom#nodejs-es-module-support"),
177179
Error::WINDOWS_PROCESS_PRNG => Some("ProcessPrng: Windows system function failure"),
180+
Error::UNEXPECTED_FILE_MUTEX_POISONED => Some("File: Initialization panicked, poisoning the mutex"),
178181
_ => None,
179182
}
180183
}

src/use_file.rs

+5-32
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ extern crate std;
44

55
use crate::{util_libc::sys_fill_exact, Error};
66
use core::{
7-
cell::UnsafeCell,
87
ffi::c_void,
98
mem::MaybeUninit,
109
sync::atomic::{AtomicI32, Ordering::Relaxed},
1110
};
1211
use std::{
1312
fs, io,
1413
os::unix::io::{IntoRawFd as _, RawFd},
14+
sync::{Mutex, PoisonError},
1515
};
1616

1717
/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
@@ -47,11 +47,10 @@ fn get_rng_fd() -> Result<RawFd, Error> {
4747

4848
#[cold]
4949
fn get_fd_locked() -> Result<RawFd, Error> {
50-
// SAFETY: We use the mutex only in this method, and we always unlock it
51-
// before returning, making sure we don't violate the pthread_mutex_t API.
52-
static MUTEX: Mutex = Mutex::new();
53-
unsafe { MUTEX.lock() };
54-
let _guard = DropGuard(|| unsafe { MUTEX.unlock() });
50+
static MUTEX: Mutex<()> = Mutex::new(());
51+
let _guard = MUTEX
52+
.lock()
53+
.map_err(|_: PoisonError<_>| Error::UNEXPECTED_FILE_MUTEX_POISONED)?;
5554

5655
if let Some(fd) = get_fd() {
5756
return Ok(fd);
@@ -151,29 +150,3 @@ fn map_io_error(err: io::Error) -> Error {
151150
}
152151
})
153152
}
154-
155-
struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
156-
157-
impl Mutex {
158-
const fn new() -> Self {
159-
Self(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))
160-
}
161-
unsafe fn lock(&self) {
162-
let r = libc::pthread_mutex_lock(self.0.get());
163-
debug_assert_eq!(r, 0);
164-
}
165-
unsafe fn unlock(&self) {
166-
let r = libc::pthread_mutex_unlock(self.0.get());
167-
debug_assert_eq!(r, 0);
168-
}
169-
}
170-
171-
unsafe impl Sync for Mutex {}
172-
173-
struct DropGuard<F: FnMut()>(F);
174-
175-
impl<F: FnMut()> Drop for DropGuard<F> {
176-
fn drop(&mut self) {
177-
self.0()
178-
}
179-
}

0 commit comments

Comments
 (0)