Panic when dropping `RwLockUpgradableReadGuard` after using `with_upgraded`
AdamLeyshon opened this issue · comments
Toolchain info:
active toolchain
----------------
stable-x86_64-unknown-linux-gnu (default)
rustc 1.72.1 (d5c2e9c34 2023-09-13)
crates
----------------
parking_lot = "0.12.1"
lock_api = "0.4.10"
Hello, I'm getting a panic when trying to drop the guard after using the with_upgraded
.
thread 'tokio-runtime-worker' panicked at /src/index.crates.io-6f17d22bba15001f/parking_lot-0.12.1/src/raw_rwlock.rs:354:21:
attempt to subtract with overflow
stack backtrace:
0: rust_begin_unwind
at /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/std/src/panicking.rs:597:5
1: core::panicking::panic_fmt
at /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/panicking.rs:72:14
2: core::panicking::panic
at /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/panicking.rs:127:5
3: <parking_lot::raw_rwlock::RawRwLock as lock_api::rwlock::RawRwLockUpgrade>::unlock_upgradable
at /src/index.crates.io-6f17d22bba15001f/parking_lot-0.12.1/src/raw_rwlock.rs:354:21
4: <lock_api::rwlock::RwLockUpgradableReadGuard<R,T> as core::ops::drop::Drop>::drop
at /src/index.crates.io-6f17d22bba15001f/lock_api-0.4.10/src/rwlock.rs:2188:13
5: core::ptr::drop_in_place<lock_api::rwlock::RwLockUpgradableReadGuard<parking_lot::raw_rwlock::RawRwLock,std::collections::hash::map::HashMap<alloc::string::String,ingest_rs::engines::helpers::InstrumentPolicyCacheEntry,ahash::random_state::RandomState>>>
at /rustc/2e5a9dd6c9eaa42f0684b4b760bd68fc27cbe51b/library/core/src/ptr/mod.rs:497:1
When hitting the BP at parking_lot-0.12.1/src/raw_rwlock.rs:354
the state
is currently usize: 4
and it's trying to subtract 20 (ONE_READER: 16 | UPGRADABLE_BIT: 4)
?
My usage looks something like this:
static POLICY_CACHE: OnceCell<RwLock<HashMap<String,InstrumentPolicyCacheEntry, RandomState>>> = OnceCell::new();
pub fn func_name(instrument: &str) -> bool {
let now = floor_dt_minute(chrono::Utc::now()).timestamp();
let mut cache_lock = POLICY_CACHE.get().unwrap().upgradable_read();
if let Some(entry) = cache_lock.get(instrument) {
if entry.expiry > now {
return entry.active;
}
}
// SNIP - Fetch the value
cache_lock.with_upgraded(|cache| {
cache.insert(instrument.to_string(), InstrumentPolicyCacheEntry { expiry: now + 60, active });
});
active
}
If I change the code to:
let mut cache_lock = RwLockUpgradableReadGuard::upgrade(cache_lock);
cache_lock.insert(instrument.to_string(), InstrumentPolicyCacheEntry { expiry: now + 60, active });
It works fine, so am I using this wrong? or is there some side-effect I'm not accounting for?
This was fixed by #393 but it wasn't published in a release. I will do this now.
Perfect!
Thank you for your amazing library and the work you do!