summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/src/docs/await_holding_lock.txt
blob: 0f450a11160ccca10c011e7fef781770c421a372 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
### 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](https://github.com/rust-lang/rust-clippy/issues/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;
}
```