rust-lang / rust-lang/rust-clippy

await_holding_lock reports explicitly dropped mutex guards as if they weren't dropped

Open
#6,446 5 comments 19 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-false-positive
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

I tried this code:

#[deny(clippy::pedantic)]
pub async fn doesnt_work() {
    use std::collections::HashSet;
    use std::sync::Mutex;
    use std::time::Duration;

    let lock: Mutex<HashSet<u8>> = Mutex::new(HashSet::new());
    let mut set = lock.lock().unwrap();
    set.insert(0);
    drop(set);
    tokio::time::sleep(Duration::from_secs(1)).await;
}

I expected to see this happen: it should pass Clippy with no linting errors because the MutexGuard is explicitly dropped before the await point with a call to std::mem::drop.

Instead, this happened: Clippy failed the lint check because of a violation of clippy::await_holding_lock:

$ cargo clippy
...
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await.
  --> src/lib.rs:8:9
   |
8  |     let mut set = lock.lock().unwrap();
   |         ^^^^^^^
   |
note: the lint level is defined here
  --> src/lib.rs:1:8
   |
1  | #[deny(clippy::pedantic)]
   |        ^^^^^^^^^^^^^^^^
   = note: `#[deny(clippy::await_holding_lock)]` implied by `#[deny(clippy::pedantic)]`
note: these are all the await points this lock is held through
  --> src/lib.rs:8:5
   |
8  | /     let mut set = lock.lock().unwrap();
9  | |     set.insert(0);
10 | |     drop(set);
11 | |     tokio::time::sleep(Duration::from_secs(1)).await;
12 | | }
   | |_^
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock

error: aborting due to previous error

Running with --verbose does not provide any additional information.

Additionally, of note, the following code does pass Clippy:

#[deny(clippy::pedantic)]
pub async fn does_work() {
    use std::collections::HashSet;
    use std::sync::Mutex;
    use std::time::Duration;

    let lock: Mutex<HashSet<u8>> = Mutex::new(HashSet::new());
    {
        let mut set = lock.lock().unwrap();
        set.insert(0);
    }
    tokio::time::sleep(Duration::from_secs(1)).await;
}
Meta
  • cargo clippy -V: clippy 0.0.212 (7eac88a 2020-11-16)
  • rustc -Vv:
    rustc 1.48.0 (7eac88abb 2020-11-16)
    binary: rustc
    commit-hash: 7eac88abb2e57e752f3302f02be5f3ce3d7adfb4
    commit-date: 2020-11-16
    host: x86_64-unknown-linux-gnu
    release: 1.48.0
    LLVM version: 11.0
    
Backtrace

$ RUST_BACKTRACE=1 cargo clippy
    Checking bug_report v0.1.0 (/home/jazev/dev/architus/logs/bug_report)
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or 
ensuring the MutexGuard is dropped before calling await.
  --> src/lib.rs:8:9
   |
8  |     let mut set = lock.lock().unwrap();
   |         ^^^^^^^
   |
note: the lint level is defined here
  --> src/lib.rs:1:8
   |
1  | #[deny(clippy::pedantic)]
   |        ^^^^^^^^^^^^^^^^
   = note: `#[deny(clippy::await_holding_lock)]` implied by `#[deny(clippy::pedantic)]`
note: these are all the await points this lock is held through
  --> src/lib.rs:8:5
   |
8  | /     let mut set = lock.lock().unwrap();
9  | |     set.insert(0);
10 | |     drop(set);
11 | |     tokio::time::sleep(Duration::from_secs(1)).await;
12 | | }
   | |_^
   = help: for further information visit https://rust-lang.github.io/rust- 
clippy/master/index.html#await_holding_lock

error: aborting due to previous error

error: could not compile `bug_report`

To learn more, run the command again with --verbose.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the reported behavior with the two Rust examples and cargo clippy, then trace the implementation of the await_holding_lock lint. Add coverage for an explicitly dropped MutexGuard and verify that the lint no longer reports it as held across the await point.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.