Skip to content

Commit

Permalink
Fixed to_thread.run_sync() hanging on asyncio on StopIteration
Browse files Browse the repository at this point in the history
Fixes #475.
  • Loading branch information
agronholm committed Oct 17, 2022
1 parent c8e5ba2 commit c0783cd
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
scope
- Fixed ``open_signal_receiver()`` inconsistently yielding integers instead of
``signal.Signals`` instances on the ``trio`` backend
- Fixed ``to_thread.run_sync()`` hanging on asyncio if the target callable raises
``StopIteration``

**3.6.1**

Expand Down
5 changes: 5 additions & 0 deletions src/anyio/_backends/_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,11 @@ def _report_result(

if not future.cancelled():
if exc is not None:
if isinstance(exc, StopIteration):
new_exc = RuntimeError("coroutine raised StopIteration")
new_exc.__cause__ = exc
exc = new_exc

future.set_exception(exc)
else:
future.set_result(result)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_to_thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,17 @@ async def taskfunc2() -> None:
task1 = asyncio_event_loop.create_task(taskfunc1())
task2 = asyncio_event_loop.create_task(taskfunc2())
asyncio_event_loop.run_until_complete(asyncio.gather(task1, task2))


async def test_stopiteration() -> None:
"""
Test that raising StopIteration in a worker thread raises a RuntimeError on the
caller.
"""

def raise_stopiteration() -> NoReturn:
raise StopIteration

with pytest.raises(RuntimeError, match="coroutine raised StopIteration"):
await to_thread.run_sync(raise_stopiteration)

0 comments on commit c0783cd

Please sign in to comment.