You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// Try to amortize the cost of loading env vars a lot as we're gonna be
// hashing for a lot of symbols.
if !HASHED.load(SeqCst){
letmut h = DefaultHasher::new();
env::var("CARGO_PKG_NAME")
.expect("should have CARGO_PKG_NAME env var")
.hash(&mut h);
env::var("CARGO_PKG_VERSION")
.expect("should have CARGO_PKG_VERSION env var")
.hash(&mut h);
// This may chop off 32 bits on 32-bit platforms, but that's ok, we
// just want something to mix in below anyway.
HASH.store(h.finish()asusize,SeqCst);
HASHED.store(true,SeqCst);
}
letmut h = DefaultHasher::new();
HASH.load(SeqCst).hash(&mut h);
self.0.hash(&mut h);
write!(f,"{:016x}", h.finish())
}
}
Race Condition:
The affected code attempts to lazily compute and cache a hash value, but the current implementation is not thread-safe. Consider the following interleaving of two threads:
Thread 1
Thread 2
check Hashed
check Hashed
recompute Hash
recompute Hash
If two threads call the fmt function concurrently, they may both observe the Hashed flag as false and proceed to recompute the hash independently. This violates the intent of computing the hash only once and leads to redundant work. While the result is ultimately consistent (assuming a stable environment), this introduces unnecessary overhead.
Memory Ordering Issue
The code currently uses Ordering::SeqCst, which is overly strict for this scenario. A combination of Ordering::Acquire and Ordering::Release is sufficient to ensure correct synchronization while allowing better performance on most architectures. But for now OnceLock is the most concise implementation.
Steps to Reproduce
Found from static analysis
Expected Behavior
No race condition. Performance increase.
Actual Behavior
In a benchmark on x86 Linux, replacing SeqCst atomics with OnceLock not only eliminated potential race conditions by ensuring the hash is computed only once, but also yielded a slight performance improvement.
Additional Context
I will submit a PR with a fix
The text was updated successfully, but these errors were encountered:
Describe the Bug
There is a race condition and a related performance issue in the following section of the wasm-bindgen codebase:
wasm-bindgen/crates/backend/src/util.rs
Lines 135 to 161 in c35cc93
The affected code attempts to lazily compute and cache a hash value, but the current implementation is not thread-safe. Consider the following interleaving of two threads:
If two threads call the fmt function concurrently, they may both observe the Hashed flag as false and proceed to recompute the hash independently. This violates the intent of computing the hash only once and leads to redundant work. While the result is ultimately consistent (assuming a stable environment), this introduces unnecessary overhead.
The code currently uses Ordering::SeqCst, which is overly strict for this scenario. A combination of Ordering::Acquire and Ordering::Release is sufficient to ensure correct synchronization while allowing better performance on most architectures. But for now OnceLock is the most concise implementation.
Steps to Reproduce
Found from static analysis
Expected Behavior
No race condition. Performance increase.
Actual Behavior
In a benchmark on x86 Linux, replacing SeqCst atomics with OnceLock not only eliminated potential race conditions by ensuring the hash is computed only once, but also yielded a slight performance improvement.
Additional Context
I will submit a PR with a fix
The text was updated successfully, but these errors were encountered: