Skip to content

Commit e8797d4

Browse files
committed
Fix deadlock detection failing during exceptions
1 parent 6b5dba4 commit e8797d4

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

asgiref/sync.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -427,25 +427,27 @@ async def __call__(self, *args, **kwargs):
427427
else:
428428
func = self.func
429429

430-
# Run the code in the right thread
431-
future = loop.run_in_executor(
432-
executor,
433-
functools.partial(
434-
self.thread_handler,
435-
loop,
436-
self.get_current_task(),
437-
sys.exc_info(),
438-
func,
439-
*args,
440-
**kwargs,
441-
),
442-
)
443-
ret = await asyncio.wait_for(future, timeout=None)
430+
try:
431+
# Run the code in the right thread
432+
future = loop.run_in_executor(
433+
executor,
434+
functools.partial(
435+
self.thread_handler,
436+
loop,
437+
self.get_current_task(),
438+
sys.exc_info(),
439+
func,
440+
*args,
441+
**kwargs,
442+
),
443+
)
444+
ret = await asyncio.wait_for(future, timeout=None)
444445

445-
if contextvars is not None:
446-
_restore_context(context)
447-
if self.deadlock_context:
448-
self.deadlock_context.set(False)
446+
finally:
447+
if contextvars is not None:
448+
_restore_context(context)
449+
if self.deadlock_context:
450+
self.deadlock_context.set(False)
449451

450452
return ret
451453

tests/test_sync.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,3 +694,26 @@ async def server_entry():
694694

695695
with pytest.raises(RuntimeError):
696696
asyncio.run(server_entry())
697+
698+
699+
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Issue persists with 3.6")
700+
def test_sync_to_async_deadlock_ignored_with_exception():
701+
"""
702+
Ensures that throwing an exception from inside a deadlock-protected block
703+
still resets the deadlock detector's status.
704+
"""
705+
706+
def view():
707+
raise ValueError()
708+
709+
async def server_entry():
710+
try:
711+
await sync_to_async(view)()
712+
except ValueError:
713+
pass
714+
try:
715+
await sync_to_async(view)()
716+
except ValueError:
717+
pass
718+
719+
asyncio.run(server_entry())

0 commit comments

Comments
 (0)