BlockingLruCache panics inside Tokio current-thread runtimes
BlockingLruCache panics when used inside Tokio's current-thread runtime instead of falling back to disabled-cache behavior.
What issue are you seeing?
- Observable sequence: construct a
BlockingLruCacheinside a Tokiocurrent_threadruntime and callinsert. - Expected: the call completes and the cache behaves as disabled, consistent with calls made outside a Tokio runtime.
- Actual:
tokio::task::block_in_placepanics because it only supports the multi-threaded runtime. - Before revision:
312caf176a. - Fix rebased and validated on current
main:74bfbda9b5. - Environment: macOS 26.5.2, Rust 1.95.0.
Actual screenshots
Before — upstream 312caf176a: the current-thread reproduction panics at block_in_place.
!Terminal reproduction showing BlockingLruCache panicking in a Tokio current-thread runtime
After — current main at 74bfbda9b5 with the focused patch: the named regression test passes without a panic.
!Terminal test showing BlockingLruCache safely disabled on a Tokio current-thread runtime
What steps can reproduce the bug?
Run this against codex-utils-cache and Tokio:
use codex_utils_cache::BlockingLruCache;
use std::num::NonZeroUsize;
#[tokio::main(flavor = "current_thread")]
async fn main() {
let cache = BlockingLruCache::new(NonZeroUsize::new(2).unwrap());
cache.insert("first", 1);
}
The panic occurs on the insert call:
thread 'main' panicked at utils/cache/src/lib.rs:127:10:
can call blocking only when running on the multi-threaded runtime
What is the expected behavior?
A current-thread runtime should use the existing disabled-cache fallback: cache operations should not panic, and an inserted entry should not be retained.
Additional information
lock_if_runtime currently checks only that a Tokio handle exists, then unconditionally calls block_in_place:
tokio::runtime::Handle::try_current().ok()?;
Some(tokio::task::block_in_place(|| m.blocking_lock()))
Handle::try_current() succeeds on both Tokio runtime flavors, but block_in_place panics on a current-thread runtime.
A focused patch is prepared that:
- reads the current Tokio runtime flavor before calling
block_in_place; - returns
Noneon a current-thread runtime, reusing the cache's existing disabled behavior; - adds a
#[tokio::test(flavor = "current_thread")]regression test provinginsertdoes not panic and the value is not retained.
Validation completed:
just test -p codex-utils-cache: 4 passed;just fix -p codex-utils-cache;just fmt.
---
I have a PR ready if issue accepted