Chris Jerdonek <chris.jerdo...@gmail.com> added the comment:

To start out sharing what I found in the Django code:

Here inside BaseHandler._get_response_async():
https://github.com/django/django/blob/3460ea49e839fd6bb924c48eaa1cd3d6dc888035/django/core/handlers/base.py#L226-L232

try:
    response = await wrapped_callback(request, *callback_args,
                                      **callback_kwargs)
except Exception as e:
    response = await sync_to_async(  # This line hangs.
        self.process_exception_by_middleware,
        thread_sensitive=True,
    )(e, request)

you can see an exception being handled, which is then passed to 
process_exception_by_middleware(). Process_exception_by_middleware() can wind 
up re-raising that same exception, which causes __context__ to be set 
circularly inside the except block:
https://github.com/django/django/blob/3460ea49e839fd6bb924c48eaa1cd3d6dc888035/django/core/handlers/base.py#L323-L332

If you boil this down, you get the following as a simple reproducer. This 
doesn't hang, but you can tell the difference by comparing exc2 to 
exc2.__context as indicated below:

import asyncio

async def process_exc(exc):
    raise exc

async def run():
    try:
        raise RuntimeError
    except Exception as exc:
        task = asyncio.create_task(process_exc(exc))
        try:
            await task
        except BaseException as exc2:
            # Prints True in 3.9.0b1 and False in 3.9.0a6.
            print(exc2 is exc2.__context__)

loop = asyncio.new_event_loop()
try:
    loop.run_until_complete(run())
finally:
    loop.close()
    
The cause is probably the following PR, which enabled exception chaining for 
gen.throw() in the yield from case:
https://github.com/python/cpython/pull/19858
So the answer might be to do some cycle detection when chaining the exception, 
which apparently _PyErr_ChainExceptions() doesn't do.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue40696>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to