question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

to_thread.run_sync() doesn't work with the tornado event loop

See original GitHub issue

Hi there!

jupyter_server uses the anyio v2 run_sync_in_worker_thread function , and I noticed a possible bug after upgrading to anyio v3.

This is the error I see when using to_thread.run_sync():

HTTPServerRequest(protocol='http', host='127.0.0.1:38403', method='GET', uri='/a%40b/api/contents/Directory%20with%20spaces%20in', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 697, in run_sync_in_worker_thread
    work_queue = _threadpool_work_queue.get()
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/anyio/lowlevel.py", line 120, in get
    raise LookupError(f'Run variable "{self._name}" has no value and no default set')
LookupError: Run variable "_threadpool_work_queue" has no value and no default set

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/tornado/web.py", line 1704, in _execute
    result = await result
  File "/home/runner/work/jupyter_server/jupyter_server/jupyter_server/services/contents/handlers.py", line 111, in get
    path=path, type=type, format=format, content=content,
  File "/home/runner/work/jupyter_server/jupyter_server/jupyter_server/utils.py", line 176, in ensure_async
    result = await obj
  File "/home/runner/work/jupyter_server/jupyter_server/jupyter_server/services/contents/filemanager.py", line 692, in get
    model = await self._dir_model(path, content=content)
  File "/home/runner/work/jupyter_server/jupyter_server/jupyter_server/services/contents/filemanager.py", line 574, in _dir_model
    dir_contents = await run_sync_in_worker_thread(os.listdir, os_dir)
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/anyio/to_thread.py", line 37, in run_sync_in_worker_thread
    return await run_sync(func, *args, cancellable=cancellable, limiter=limiter)
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/anyio/to_thread.py", line 29, in run_sync
    limiter=limiter)
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 707, in run_sync_in_worker_thread
    find_root_task().add_done_callback(_loop_shutdown_callback)
  File "/opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 56, in find_root_task
Error:     raise RuntimeError('Cannot find root task for setting cleanup callback')

It looks like the find_root_task function is failing because the callback is a tornado.ioloop and not an uvloop.loop.

Jupyter server is using the tornado event loop. For more context, this is the github issue: https://github.com/jupyter-server/jupyter_server/issues/487

Possible Solution

I was able to fix it by updating the following code, but I’m not sure if this is a proper fix.
src/anyio/_backends/_asyncio.py line 50

if cb is _run_until_complete_cb or cb.__module__ in ('uvloop.loop', 'tornado.ioloop')

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:10 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
agronholmcommented, Apr 30, 2021

I’ve released v3.0.1 with this fix now.

1reaction
agronholmcommented, Apr 22, 2021

I will try to resolve this over the coming weekend.

Read more comments on GitHub >

github_iconTop Results From Across the Web

tornado.ioloop — Main event loop
An I/O event loop. As of Tornado 6.0, IOLoop is a wrapper around the asyncio event loop. ... Most applications should not attempt...
Read more >
Cannot run the event loop while another loop is running ...
I'm trying to make synchronous requests using Tornado. Tried to make API calls. main.py
Read more >
asyncio event loop or IOLoop ? - Google Groups
Hi,. Since now Tornado plays perfectly with async/await, which means we can directly use Async/Await libraries for databases, right ? for example ...
Read more >
A Beginner's Guide to Python Tornado - Velotio
It uses an event loop design that makes Tornado request execution faster. ... As the CPU is not idle, there is no need...
Read more >
Asynchronous Computation — Streamz 0.6.4 documentation
There are a few different ways to use Streamz with a Tornado event loop. ... function that was not designed to work asynchronously...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found