You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[mypyc] Fix exception swallowing in async try/finally blocks with await
When a try/finally block in an async function contains an await statement
in the finally block, exceptions raised in the try block are silently
swallowed if a context switch occurs. This happens because mypyc stores
exception information in registers that don't survive across await points.
The Problem:
- mypyc's transform_try_finally_stmt uses error_catch_op to save exceptions
to a register, then reraise_exception_op to restore from that register
- When await causes a context switch, register values are lost
- The exception information is gone, causing silent exception swallowing
The Solution:
- Add new transform_try_finally_stmt_async for async-aware exception handling
- Use sys.exc_info() to preserve exceptions across context switches instead
of registers
- Check error indicator first to handle new exceptions raised in finally
- Route to async version when finally block contains await expressions
Implementation Details:
- transform_try_finally_stmt_async uses get_exc_info_op/restore_exc_info_op
which work with sys.exc_info() that survives context switches
- Proper exception priority: new exceptions in finally replace originals
- Added has_await_in_block helper to detect await expressions
Test Coverage:
Added comprehensive async exception handling tests:
- testAsyncTryExceptFinallyAwait: 8 test cases covering various scenarios
- Simple try/finally with exception and await
- Exception caught but not re-raised
- Exception caught and re-raised
- Different exception raised in except
- Try/except inside finally block
- Try/finally inside finally block
- Control case without await
- Normal flow without exceptions
- testAsyncContextManagerExceptionHandling: Verifies async with still works
- Basic exception propagation
- Exception in __aexit__ replacing original
See mypyc/mypyc#1114
0 commit comments