{"record":{"id":"3c44a810390d5975","repo":"embassy-rs/embassy","slug":"the-rng-is-in-use","errorCode":null,"errorMessage":"the RNG is in use","messagePattern":"the RNG is in use","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/rng.rs","lineNumber":678,"sourceCode":"pub(crate) mod driver {\n    use embassy_crypto::Error as CryptoError;\n    use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;\n    use embassy_sync::mutex::Mutex;\n\n    use super::{MAX_RESET_RETRIES, Rng};\n    use crate::mode::Blocking;\n\n    foreach_peripheral!(\n        (rng, $inst:ident) => {\n            type Instance = crate::peripherals::$inst;\n        };\n    );\n\n    static DRIVER: Mutex<CriticalSectionRawMutex, Option<Rng<'static, Blocking>>> = Mutex::new(None);\n\n    /// Runs `f` on the RNG, starting it first if needed.\n    pub(crate) fn with_rng<R>(f: impl FnOnce(&mut Rng<'static, Blocking>) -> R) -> R {\n        let mut driver = DRIVER.try_lock().expect(\"the RNG is in use\");\n        let rng = driver.get_or_insert_with(|| {\n            let peri = unsafe { Instance::steal() };\n            #[cfg(rng_v1)]\n            {\n                Rng::new_inner(peri)\n            }\n            #[cfg(not(rng_v1))]\n            {\n                Rng::new_inner(peri, super::RngConfig::default())\n            }\n        });\n        f(rng)\n    }\n\n    /// Starts the RNG if it is not running yet.\n    pub(crate) fn ensure_running() {\n        with_rng(|_| ());\n    }","sourceCodeStart":660,"sourceCodeEnd":696,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/rng.rs#L660-L696","documentation":"The embassy RNG global driver is guarded by a `Mutex` over a single `Option<Rng<'static, Blocking>>`. `with_rng` uses `try_lock` and panics with \"the RNG is in use\" if the lock is already held — meaning two tasks (or an interrupt context) are concurrently using the RNG. Embassy mutexes are not reentrant, so nested/parallel access is a hard error.","triggerScenarios":"Two async tasks concurrently calling RNG-backed APIs (e.g. `fill_bytes` via `Rng`/random helpers); calling an RNG function from inside another RNG callback (re-entrant nesting) so the mutex is locked twice in the same execution context.","commonSituations":"Multiple subsystems (TLS, device ID generation, UUID generation) sampling randomness simultaneously; spawning two tasks that both draw entropy at startup; blocking RNG call inside an async context that also uses the RNG from an executor thread.","solutions":["Serialize RNG access yourself: perform random reads from a single task, or use a channel/actor that owns randomness","Retry or defer one consumer — since it's `try_lock`, moving the second call to another tick avoids contention","Check for accidental nesting: don't call another RNG-based API while holding a random-generating call (e.g. generating a UUID inside `fill_bytes` handling)","Use an embassy `signal`/`mutex` wrapper so callers await instead of panicking"],"exampleFix":"// before\nlet a = rand_bytes().await;   // task A\nlet b = rand_bytes().await;   // task B, same tick -> try_lock panic\n// after\nstatic RNG_SEM: Semaphore<1> = Semaphore::new(1);\nlet permit = RNG_SEM.acquire().await;\nlet a = rand_bytes().await;\ndrop(permit); // then task B proceeds safely","handlingStrategy":"validation","validationCode":"// Ensure only one task generates randomness at a time\nstatic RNG_GATE: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());\nlet _g = RNG_GATE.lock().await; // serialize callers instead of try_lock panicking","typeGuard":null,"tryCatchPattern":"// Embassy panics aren't catchable; avoid contention instead:\nmatch DRIVER.try_lock() {\n    Ok(_) => { /* safe to generate randomness */ }\n    Err(_) => { /* defer to next tick or return Pending */ }\n}","preventionTips":["Funnel all randomness through one dedicated task/actor","Never nest RNG-based calls inside another RNG operation","Audit that no interrupt context calls RNG-backed APIs","Add an owned semaphore around random generation in application code"],"tags":["embedded","rng","concurrency","mutex","panic"],"backgroundTag":"resource-conflict","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}