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
Asyncio Lock safety issue (unlimited acquire) #76915
Comments
Hey guys, I found a pretty dangerous bug that allows acquiring locks in asyncio without them being free. This happens due to double release (calling _wake_up_first) from both release and acquire in case of cancellation. The example I've uploaded exploits it by acquiring 4 times, which grooms the loop's _ready queue, cancelling the second acquire to add the cancellation to the _ready queue, and releasing once to add the next waiter (number 3) to the _ready queue. Next event loop step causes the cancellation to run first, skipping the queued waiter (due to .done check being true) and waking the next waiter in line (number 4). Then both number 3 and number 4 run together on the same Lock. I'm not at home so it's hard for me to code but the simple way of fixing it is by adding this line - "if self._locked: yield from self.acquire()" after the "yield from fut" (quite minimal overhead and only if bug happens, so no harm) or by slightly restructuring the code and the checks regarding cancelled futures. I can later on post the restructured code but I think the simple if statement is a pretty fine and efficient fix. |
Alright. Fixed, added tests, news and acks. |
Finished fixing CR and adding backports. |
Thank you, Bar! Looking forward to see more contributions to asyncio from you! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: