Lock guard is still alive across an .await
ID |
rust.correctness.await_holding_lock |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Concurrency |
Language |
Rust |
Description
The guard returned by this lock is still in scope when the task suspends at the .await, so the lock stays held while another task runs and any task that needs it blocks — a deadlock if that task is what the awaited future is waiting for. Narrow the guard to its own block, or drop it before the .await.
Rationale
The guard returned by this lock is still in scope when the task suspends at the .await, so the lock stays held while another task runs and any task that needs it blocks — a deadlock if that task is what the awaited future is waiting for. Narrow the guard to its own block, or drop it before the .await.
The following code illustrates the pattern detected by this rule:
use std::sync::{Mutex, RwLock};
async fn persist(_value: u32) {}
pub async fn counter(state: &Mutex<u32>) {
// FLAGGED: Lock guard is still alive across an `.await`
let guard = state.lock().unwrap();
persist(*guard).await;
println!("{}", *guard);
}