Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diagnostics dont work because they dont have access to the event loop #259

Open
jopotochnykorbit opened this issue Feb 21, 2023 · 0 comments

Comments

@jopotochnykorbit
Copy link

To reproduce

  1. Fork/Clone this project
  2. Run the server using a websocket, e.g. poetry run jedi-language-server --ws --verbose --log-file .logs.txt
  3. Using any client (or use the monaco-languageclient example, instructions to which can be found here, get the client to emit one of textDocument/didOpen, textDocument/didChange, textDocument/didSave, textDocument/didClose or textDocument/hover.
  4. The server should spit out many errors that are all RuntimeError: There is no current event loop in thread X

When I forked this project and ran it locally, using the monaco-languageclient react client example as a client, I kept getting crashes when the diagnostic actions (e.g. textDocument/didOpen, textDocument/didChange, textDocument/didSave, textDocument/didClose and textDocument/hover) were being emitted. The error I was getting was:
RuntimeError: There is no current event loop in thread X

After a few hours of debugging, I realized that it was coming from this file, where the Diagnostic methods are being run in a thread using Timer. This leads to that thread not having an event loop to send things via websocket.

I fixed this by replacing lines 68 - 80 with:

async def run() -> None:
    with lock:
        del timers[key]
    return func(*args, **kwargs)

with lock:
    old_timer = timers.get(key)
    if old_timer:
        old_timer.cancel()

    timer = threading.Timer(interval_s, asyncio.run_coroutine_threadsafe, args=(run(), asyncio.get_running_loop()))
    timers[key] = timer
    timer.start()

This ensures that the thread has an event loop to use, and changing it to this made the diagnostic actions work again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant