This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author bar.harel
Recipients asvetlov, bar.harel, yselivanov
Date 2018-01-31.18:55:45
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1517424945.58.0.467229070634.issue32734@psf.upfronthosting.co.za>
In-reply-to
Content
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.
History
Date User Action Args
2018-01-31 18:55:45bar.harelsetrecipients: + bar.harel, asvetlov, yselivanov
2018-01-31 18:55:45bar.harelsetmessageid: <1517424945.58.0.467229070634.issue32734@psf.upfronthosting.co.za>
2018-01-31 18:55:45bar.harellinkissue32734 messages
2018-01-31 18:55:45bar.harelcreate