Yury Selivanov added the comment:

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 

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 

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.

Added file: http://bugs.python.org/file39354/with.patch

Python tracker <rep...@bugs.python.org>
Python-bugs-list mailing list

Reply via email to