ruby-lsp icon indicating copy to clipboard operation
ruby-lsp copied to clipboard

Multiple workspace folders result in too many ruby-lsp processes using vscode-ruby-lsp

Open stillhart opened this issue 10 months ago • 5 comments

Description

Note: I am aware that ruby-lsp spawns a process for each open workspace folder in vscode. That is expected. In my case it is spawning a lot of processes for a specific project folder, which is unexpected.

Reproduction steps

Using

  • vscode-ruby-lsp
  • MacOS to RHEL7 remote
  • chruby
  • ruby 3.3.0
  • multiple vscode projects folders being gems or rails projects (File - add folder to workspace)
  • chruby as ruby version manager in the vscode-ruby-lsp settings
  • pointing directly to a folder having ruby-lsp installed ruby-lsp: bundle gemfile setting

Using "healthy" folders in the workspace

I can add multiple projects to a vscode window and ruby-lsp starts normally

# Vscode ruby lsp output
2024-04-02 12:21:51.151 [info] (app1) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 12:21:52.519 [info] (app1) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 12:21:53.764 [info] (app2) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 12:21:54.126 [info] (app2) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 12:21:55.908 [info] (app1) Ruby LSP detected this is a Sorbet project so will defer to Sorbet LSP for some functionality
2024-04-02 12:21:55.909 [info] (app1) Initializing Ruby LSP v0.15.0...
2024-04-02 12:21:56.987 [info] (app1) Finished initializing Ruby LSP!
2024-04-02 12:21:56.988 [info] (app2) Ruby LSP detected this is a Sorbet project so will defer to Sorbet LSP for some functionality
Initializing Ruby LSP v0.15.0...
2024-04-02 12:21:57.020 [info] (app2) Finished initializing Ruby LSP!

Adding "unhealthy" folders to the workspace

After I add certain rails apps vscode-ruby-lsp suddenly starts spawning a lot of processes for that single added rails project. That behavior multiplies for each of these projects.

# Vscode ruby lsp output
2024-04-02 13:37:31.622 [info] (app1) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:32.470 [info] (app1) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:33.064 [info] (app2) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:33.365 [info] (app2) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:35.403 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.404 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.405 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:35.406 [info] (lsp-unhappy-app) Discovered Ruby version ruby-3.3.0 from file:///scratch/stillhart/ruby-lsp/.ruby-version
2024-04-02 13:37:37.090 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.090 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.090 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.090 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.091 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.092 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:37.093 [info] (lsp-unhappy-app) Activated Ruby environment: defaultGems=/opt/rubies/ruby-3.3.0/lib/ruby/gems/3.3.0 gemHome=/home/stillhart/.gem/ruby/3.3.0 yjit=true
2024-04-02 13:37:38.372 [info] (app1) Starting Ruby LSP v0.15.0...
2024-04-02 13:37:38.432 [info] (app2) Starting Ruby LSP v0.15.0...
2024-04-02 13:37:41.206 [info] (app2) Ruby LSP is ready
Ruby LSP Rails booting server
2024-04-02 13:37:41.488 [info] (app1) Ruby LSP is ready
2024-04-02 13:37:41.538 [info] (app1) Ruby LSP Rails booting server
# ... server gets overloaded

That of course kills my server due to high CPU and memory usage.

Setup

ruby --version
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]

chruby
   ruby-3.2.2
 * ruby-3.3.0
    "rubyLsp.formatter": "rubocop",
    "rubyLsp.rubyVersionManager": "chruby",
    "rubyLsp.bundleGemfile": "/scratch/stillhart/ruby-lsp/Gemfile",
# /scratch/stillhart/ruby-lsp/Gemfile
source 'https://rubygems.org'
gem "ruby-lsp"
# /scratch/stillhart/ruby-lsp/Gemfile.lock
GEM
  remote: https://rubygems.org
  specs:
    language_server-protocol (3.17.0.3)
    prism (0.24.0)
    ruby-lsp (0.15.0)
      language_server-protocol (~> 3.17.0)
      prism (>= 0.22.0, < 0.25)
      sorbet-runtime (>= 0.5.10782)
    sorbet-runtime (0.5.11323)

PLATFORMS
  aarch64-linux
  arm64-darwin
  universal-darwin
  x86_64-darwin
  x86_64-linux

DEPENDENCIES
  ruby-lsp

BUNDLED WITH
   2.5.4

Other

I am unable to pin down why it happens in these folders. I don't even know where to start but it feels like a bug or race condition within vscode-ruby-lsp. I already tried a variety of settings but I just could not solve my problem.

stillhart avatar Apr 02 '24 12:04 stillhart

Thank you for reporting this issue! It does indeed seem like some sort of race condition.

A few questions to help understand what's going on:

  1. If you open the "unhealthy" workspace on its own, without being a part of a multi workspace configuration, do you still see the problem?
  2. Does the "unhealthy" workspace have Ruby files already opened in the UI when you open the editor? How about the healthy ones?

Not 100% sure yet, but I'm suspecting there might be a race condition in our lazy activation here.

vinistock avatar Apr 02 '24 13:04 vinistock

If you open the "unhealthy" workspace on its own, without being a part of a multi workspace configuration, do you still see the problem?

No

Does the "unhealthy" workspace have Ruby files already opened in the UI when you open the editor? How about the healthy ones?

Neither, it can happen without any files being open.

But it seems like you are kinda right. I have no issues if I open these projects in a separate window. It only start to happens once I have two or more added folders. Maybe I'm lucky but it seems to happen on subsequent folders only, never for the first once.

stillhart avatar Apr 04 '24 12:04 stillhart

I have no experience with typescript, but that loop in chruby looks suspicious to me https://github.com/Shopify/ruby-lsp/blob/044568eb7de2f6bc10ee9e012c213804e7663412/vscode/src/ruby/chruby.ts#L84 Because I get a lot of these messages in my output https://github.com/Shopify/ruby-lsp/blob/044568eb7de2f6bc10ee9e012c213804e7663412/vscode/src/ruby/chruby.ts#L106

Chruby has the sad behavior that it doesn't even set a default ruby version if I'm outside of a .ruby-version file. So I'm having multiple .ruby-version files across my file system. Could that help to elevate the issue?

/home/stillhart/.ruby-version
/scratch/.ruby-version
/scratch/stillhart/.ruby-version
/scratch/stillhart/app1/.ruby-version
/scratch/stillhart/app2/.ruby-version
/scratch/stillhart/lsp-unhappy-app/.ruby-version

// Edit: removing .ruby-version files does not change the situation.

stillhart avatar Apr 04 '24 12:04 stillhart

I'm able to reproduce the problem on MacOS using Ruby 3.3.0, 3 new rails apps (rails new + bundle add ruby-lsp) and chruby.

stillhart avatar Apr 05 '24 09:04 stillhart

Unfortunately, I haven't been able to reproduce this, so I'm unsure about where the bug is exactly. Since we're awaiting the readFile promise, that while loop shouldn't be causing any issues - although I could be wrong.

If you can reliably reproduce it and would like to debug, here is a suggestion of how to approach it:

  1. Clone ruby-lsp
  2. Install node dependencies (cd vscode && yarn install)
  3. Add a bunch of prints in the Chruby class. We need to understand exactly which promise is not being properly awaited for resolution. Use the output channel to get that information in the output tab
this.outputChannel.info("something")
  1. In the Run and debug panel, select the Run extension task and click run. That will open a second VS Code window where the development version of the extension is running
  2. In that second window, take the steps to reproduce the issue
  3. Check the output tab of the second window to see the new prints

If we can pin point exactly which promise is allowing for the race condition, then we can fix this.

vinistock avatar Apr 12 '24 15:04 vinistock

This issue is being marked as stale because there was no activity in the last 2 months

github-actions[bot] avatar Jun 12 '24 12:06 github-actions[bot]