Amanieu / parking_lot

Compact and efficient synchronization primitives for Rust. Also provides an API for creating custom synchronization primitives.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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!