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 yselivanov
Recipients asvetlov, gvanrossum, ncoghlan, python-dev, scoder, vstinner, yselivanov
Date 2015-05-13.03:36:01
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1431488163.37.0.65142555224.issue24017@psf.upfronthosting.co.za>
In-reply-to
Content
Nick, Guido,

Attached is a patch that fixes a refleak in 'async with' implementation.

The problem is related to WITH_CLEANUP_START/WITH_CLEANUP_FINISH opcodes.

For regular 'with' statements, these opcodes go one after another (essentially, it was one opcode before 'async with').

For 'async with' statements, we have a GET_AWAITABLE/YIELD_FROM pair between them.

Now, if an error occurred during running a GET_AWAITABLE or a YIELD_FROM opcode, WITH_CLEANUP_FINISH was unreachable.  All blocks were correctly unwound by the eval loop, but exception object got too many DECREFS.

My solution is to continue using WITH_CLEANUP_START/WITH_CLEANUP_FINISH opcodes, but use SETUP_EXCEPT to guard them and nested YIELD_FROM and GET_AWAITABLE.

In case of an exception, I propose to use another new opcode -- ASYNC_WITH_CLEANUP_EXCEPT.  It unwinds the block set up by SETUP_EXCEPT, restores exception, NULLifies a copy of exception in the stack and does 'goto error', letting eval loop do the rest.

"./python.exe -m test -R3:3 test_coroutines" with this patch reports no refleaks.  I also updates test_coroutines with a lot of new 'async with' tests, I think that I got all usecases covered.

Please take a look at the patch, I want to commit it as soon as possible.
History
Date User Action Args
2015-05-13 03:36:04yselivanovsetrecipients: + yselivanov, gvanrossum, ncoghlan, scoder, vstinner, asvetlov, python-dev
2015-05-13 03:36:03yselivanovsetmessageid: <1431488163.37.0.65142555224.issue24017@psf.upfronthosting.co.za>
2015-05-13 03:36:03yselivanovlinkissue24017 messages
2015-05-13 03:36:03yselivanovcreate