-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Async iterators permit yield return inside of lock blocks #72443
Comments
@jjonescz let's address this as part of relaxing the restrictions around |
This has been discussed in LDM, Jun 3, 2024, as part of review of the ref-in-async feature. The conclusion was that we should remove this warning to avoid a breaking change (especially given our recent breaking changes, we don't want to make the situation worse) and it was pointed out that this could be an analyzer instead. The decision wasn't final because it was pointed out that |
I'm sorry I had to leave the meeting early. 😦
Is there a fundamental difference between it being implemented in the compiler and it being implemented in an analyzer that ships in the .NET SDK and is enabled by default? |
Version Used:
d8d7886
Steps to Reproduce:
SharpLab
Expected Behavior:
Fails to compile, with an error about not yielding while holding a lock.
Actual Behavior:
Compiles without error, but blows up at runtime with an exception:
Since normal synchronous
IEnumerable<T>
iterators were introduced,yield return
has unfortunately been allowed while holding alock
. This is problematic because it means the caller iterating through the iterator will also be holding the lock, e.g. this:prints this:
It appears async iterators have inherited the same lack of constraint around using
yield return
inside of a lock, but the problems are compounded because with an async iterator, the caller will very likely beawait
'ing other things while iterating, which then means that it's likely the eventual call into the async iterator'sMoveNext
that releases the lock will be on a different thread than the one which acquired it. Moreover, in the interim other work that runs on the thread that was holding the lock will see that it's holding the lock, and will be able to observe any invariants that might not no longer hold. Async methods and async iterators disallow usingawait
inside of alock
, but allowingyield return
can effectively amount to the same thing, since the caller will beawait
'ing things.Ideally this would have been a hard error. If it's too late to do that, we should really have a warning about
yield return
inside of alock
, ideally for both async and sync iterators, but at a minimum for async.The text was updated successfully, but these errors were encountered: