-
Notifications
You must be signed in to change notification settings - Fork 24
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
Move salsa cancellation into Drop for Server
#74
Conversation
This fixes a potential deadlock if the language server is quit at a bad time.
Drop for Server
Drop for Server
Bah actually this is incorrect, drop isn't what's hanging. This change could be considered just to be closer to rust-analyzer but it doesn't solve #36 - I had other changes locally that should solve that. |
FYI we will be migrating to the updated salsa later this quarter, when it lands in RA. See rust-lang/rust-analyzer#18964 |
And I think the way to deal with it is to forbid database updates after a shutdown is received. Let me take a look. |
@the-mikedavis the way I see it is that we do not update the salsa database after we receive the shutdown request erlang-language-platform/crates/elp/src/server.rs Lines 498 to 502 in 6750dab
We do update the vfs store, based on document |
It looks like rust-analyzer is keeping its call to I should note that the deadlock doesn't appear to be in salsa itself but in the Backtraces...The main thread:
Most other threads are idle but thread 68:
The exact task that the thread is doing seems to change between reproductions of the hang. |
I think the deadlock happens only when a task is kicked off before the shutdown request but doesn't complete before Server is dropped. Also this deadlock only happens when the logger deadlock is fixed - you can comment out the body of |
Summary: This fixes two possible deadlocks that cause `elp server` to hang during exit. I was on the right track in #74 but there are actually two deadlocks: * The first happens because the logger backend has a clone of the `Sender` of the `Connection` (because the `LspLogger` clones it one). This can cause a deadlock when a message is _not_ logged following the drop of `Server` on `io_threads.join()` because the `Connection`'s thread for receiving messages from the `Connection`'s `Receiver` awaits messages indefinitely. The solution for this deadlock is to remove the `LspLogger` from the backend on `Drop` of the server (or any time earlier). That decrements the reference count on the `Sender` and causes the `Receiver`'s iterator to return `None` resulting in the termination of its thread. * The second I don't really understand fully. The `Drop for Server` hangs because the cache task pool's drop joins its threads (by design) and there is an outstanding task that seems to be frozen, I think related to Salsa's cancellation mechanism. Explicitly requesting cancellation during drop eliminates this problem. Plus it matches what rust-analyzer does. Fixes #36 Pull Request resolved: #75 Reviewed By: michalmuskala Differential Revision: D69115301 Pulled By: alanz fbshipit-source-id: 3b0a5b39f49d668199a2370f1b23bc78f0ae6d17
I'm not super familiar with the salsa internals but it seems as though if the database is modified between the receipt of
request::Shutdown
andnotification::Exit
then theDrop
forServer
deadlocks. This is fairly easy to trigger especially on a debug build by quitting an editor like neovim soon after starting the language server. Moving the cancellation request intoDrop
matches rust-analyzer and seems to avoid the deadlock - I believe because it closes the window where the database could be edited between cancel and drop.Fixes #36