RS.CLIPPY.AWAIT_HOLDING_LOCK
Inside an async function, holding a `MutexGuard` while calling `await`
This checker is a Clippy lint created by The Rust Project Contributors. The documentation shown here is a copy of the original documentation for: await_holding_lock. Copyright ©2025 The Rust Team. All rights reserved.
What it does
Checks for calls to await while holding a non-async-aware
MutexGuard.
Why is this bad?
The Mutex types found in std::sync and
parking_lot are
not designed to operate in an async context across await points.
There are two potential solutions. One is to use an async-aware Mutex
type. Many asynchronous foundation crates provide such a Mutex type.
The other solution is to ensure the mutex is unlocked before calling
await, either by introducing a scope or an explicit call to
Drop::drop.
Known problems
Will report false positive for explicitly dropped guards
(#6446). A
workaround for this is to wrap the .lock() call in a block instead of
explicitly dropping the guard.
Example
async fn foo(x: &Mutex<u32>) {
let mut guard = x.lock().unwrap();
*guard += 1;
baz().await;
}
async fn bar(x: &Mutex<u32>) {
let mut guard = x.lock().unwrap();
*guard += 1;
drop(guard); // explicit drop
baz().await;
}
Use instead:
async fn foo(x: &Mutex<u32>) {
{
let mut guard = x.lock().unwrap();
*guard += 1;
}
baz().await;
}
async fn bar(x: &Mutex<u32>) {
{
let mut guard = x.lock().unwrap();
*guard += 1;
} // guard dropped here at end of scope
baz().await;
}