From b14f32d65bfc91529afa5a5b8e80a781a9dacd20 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Wed, 9 Jul 2025 15:07:54 -0400 Subject: [PATCH] Avoid writing error file if client is closed during bundle compose --- lib/ruby_lsp/setup_bundler.rb | 8 ++++++++ test/setup_bundler_test.rb | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/ruby_lsp/setup_bundler.rb b/lib/ruby_lsp/setup_bundler.rb index 3303e16fcc..d358d01c9a 100644 --- a/lib/ruby_lsp/setup_bundler.rb +++ b/lib/ruby_lsp/setup_bundler.rb @@ -234,6 +234,14 @@ def run_bundle_install(bundle_gemfile = @gemfile) # If no error occurred, then clear previous errors @error_path.delete if @error_path.exist? $stderr.puts("Ruby LSP> Composed bundle installation complete") + rescue Errno::EPIPE + # If the $stderr pipe was closed by the client, for example when closing the editor during running bundle + # install, we don't want to write the error to a file or else we will report to telemetry on the next launch and + # it does not represent an actual error. + # + # This situation may happen because while running bundle install, the server is not yet ready to receive + # shutdown requests and we may continue doing work until the process is killed. + @error_path.delete if @error_path.exist? rescue => e # Write the error object to a file so that we can read it from the parent process @error_path.write(Marshal.dump(e)) diff --git a/test/setup_bundler_test.rb b/test/setup_bundler_test.rb index c32d202a2d..12c8d6a82c 100644 --- a/test/setup_bundler_test.rb +++ b/test/setup_bundler_test.rb @@ -914,6 +914,28 @@ def test_ignores_bundle_package end end + def test_is_resilient_to_pipe_being_closed_by_client_during_compose + Dir.mktmpdir do |dir| + Dir.chdir(dir) do + File.write(File.join(dir, "gems.rb"), <<~GEMFILE) + source "https://rubygems.org" + gem "irb" + GEMFILE + + Bundler.with_unbundled_env do + capture_subprocess_io do + system("bundle install") + + compose = RubyLsp::SetupBundler.new(dir, launcher: true) + compose.expects(:run_bundle_install_directly).raises(Errno::EPIPE) + compose.setup! + refute_path_exists(File.join(dir, ".ruby-lsp", "install_error")) + end + end + end + end + end + private def with_default_external_encoding(encoding, &block)