Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lint for using await while holding a MutexGuard #4226

Closed
tkaitchuck opened this issue Jun 22, 2019 · 13 comments · Fixed by #5439
Closed

Lint for using await while holding a MutexGuard #4226

tkaitchuck opened this issue Jun 22, 2019 · 13 comments · Fixed by #5439
Assignees
Labels
A-lint Area: New lints L-correctness Lint: Belongs in the correctness lint group T-async-await Type: Issues related to async/await

Comments

@tkaitchuck
Copy link

It would be useful to implement a lint against calling .await while a holding a MutexGuard.
This is almost certainly an error (and a non-obvious one) because the Reactor is going to end up invoking code not visible in the current scope while the lock is held.

@flip1995 flip1995 added L-correctness Lint: Belongs in the correctness lint group A-lint Area: New lints T-async-await Type: Issues related to async/await labels Jun 22, 2019
@tmandry
Copy link
Member

tmandry commented Oct 4, 2019

With a recent change to .await semantics (rust-lang/rust#64292), the following pattern now holds a lock across await where it didn't before:

thing.lock().foo().await

This kind of lint may become more important for those used to the old behavior.

FYI, in Fuchsia, we had 8 instances of this in our codebase at the time of updating to a compiler with the new semantics. 6 of them were caught by compiler errors, but 2 weren't.

@nayato
Copy link

nayato commented Dec 11, 2019

@tmandry I think the argument being made is that it is usually bad idea to take a lock and hold to across await. I'm making the same argument in #4893 in generic way.

@tmandry
Copy link
Member

tmandry commented Dec 12, 2019

@tmandry I think the argument being made is that it is usually bad idea to take a lock and hold to across await. I'm making the same argument in #4893 in generic way.

Yes; I'm saying that this is easier to do accidentally now. I like your suggestion also.

@tmandry
Copy link
Member

tmandry commented Apr 3, 2020

Implementation notes:

I think roughly what we want to do here is iterate over all async fns/async blocks in our crate (probably using intravisit), get their TypeckTables, and iterate over all types in generator_interior_types, checking for any types named MutexGuard.

Ideally this would support mutex implementations other than the standard library (such as parking_lot), which is I suggest checking the type name. We can also look for names like RwLockReadGuard and RwLockWriteGuard.

So far it's unclear to me whether parking_lot's reentrant locks should be included.

@flip1995
Copy link
Member

flip1995 commented Apr 3, 2020

Other lints about mutexes only lint on std types. I'd suggest to do the same here.

@tmandry
Copy link
Member

tmandry commented Apr 3, 2020

@flip1995 that makes the lint less useful and catches fewer bugs. Anything named MutexGuard is bound to apply, so I think we should do it at least for the set of names std uses.

@rokob
Copy link
Contributor

rokob commented Apr 7, 2020

Hey I'm interested in taking this on. I will put together a WIP PR based on the guidance above and we can take it from there.

@tmandry
Copy link
Member

tmandry commented Apr 7, 2020

@rustbot assign @rokob

rokob added a commit to rokob/rust-clippy that referenced this issue Apr 8, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
rokob added a commit to rokob/rust-clippy that referenced this issue Apr 8, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
@nayato
Copy link

nayato commented Apr 8, 2020

@tmandry would it make sense to expand to Ref<T> and RefMut<T>? I think RefCell.borrow()/borrow_mut() being held across await point is as controversial and potentially more dangerous.
Of course it is limited to !Send futures only but still.

@tmandry
Copy link
Member

tmandry commented Apr 9, 2020

@tmandry would it make sense to expand to Ref<T> and RefMut<T>? I think RefCell.borrow()/borrow_mut() being held across await point is as controversial and potentially more dangerous.
Of course it is limited to !Send futures only but still.

Yeah, probably! Though I'd be inclined to make it a separate lint. (I could be convinced otherwise)

@rokob
Copy link
Contributor

rokob commented Apr 10, 2020

So the PR is up and there was feedback to match against the full paths of the mutex types. I'm new to this codebase so I'm not sure how to arbitrate that, but I agree wit the above comment that doing so makes this lint much less useful. I made the change to match against full paths to see what it would look like, but I think switching back to just matching against anything named "MutexGuard" is more useful.

rokob added a commit to rokob/rust-clippy that referenced this issue Apr 17, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
rokob added a commit to rokob/rust-clippy that referenced this issue Apr 17, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
rokob added a commit to rokob/rust-clippy that referenced this issue Apr 17, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
rokob added a commit to rokob/rust-clippy that referenced this issue Apr 17, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
rokob added a commit to rokob/rust-clippy that referenced this issue Apr 17, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
rokob added a commit to rokob/rust-clippy that referenced this issue Apr 17, 2020
Fixes rust-lang#4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.
bors added a commit that referenced this issue Apr 22, 2020
Lint for holding locks across await points

Fixes #4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.

changelog: introduce the await_holding_lock lint
bors added a commit that referenced this issue Apr 22, 2020
Lint for holding locks across await points

Fixes #4226

This introduces the lint await_holding_lock. For async functions, we iterate
over all types in generator_interior_types and look for types named MutexGuard,
RwLockReadGuard, or RwLockWriteGuard. If we find one then we emit a lint.

changelog: introduce the await_holding_lock lint
@bors bors closed this as completed in 6c25c3c Apr 22, 2020
@goffrie
Copy link

goffrie commented May 1, 2020

Should this lint also be extended to RefCell borrows? It seems they are very similar in this regard.

@tmandry
Copy link
Member

tmandry commented May 2, 2020

Should this lint also be extended to RefCell borrows? It seems they are very similar in this regard.

Yes, this was brought up earlier. I thought they should probably be separate lints, but don't have a strong opinion here. Please open an issue to discuss further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints L-correctness Lint: Belongs in the correctness lint group T-async-await Type: Issues related to async/await
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

6 participants