From 41050159289478f7d230ffeddda3eb1af4264355 Mon Sep 17 00:00:00 2001 From: Thomas Marshall Date: Tue, 1 Oct 2024 15:48:58 +0100 Subject: [PATCH] Fix reloading in Ruby 3.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit ensures the application is restarted when a preloaded file is changed. This has been silently broken because the fallback behavior still results in the application being restarted, but only when the user next runs a command—hence the acceptance test still passing. The behavior of `BasicSocket#recv` changed in Ruby 3.3 [1] such that it now returns `nil` on a closed stream socket, instead of an empty string. When we call `#empty?` on `nil` the `NoMethodError` is swallowed by the failsafe thread and the application is not restarted. This commit fixes the issue by checking both `#nil?` and `#empty?` so it works with both old and new versions. It also updates the acceptance test to be more specific about what it considers a "reload" by asserting the relevant log line exists. [1]: https://github.com/ruby/ruby/pull/6407 --- CHANGELOG.md | 2 ++ lib/spring/application_manager.rb | 3 ++- test/support/acceptance_test.rb | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccacc975..cc3c783f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Next Release +* Fix reloading issue in Ruby 3.3. + ## 4.2.1 * Added `Spring.connect_timeout` and `Spring.boot_timeout` to allow to increase timeout for larger apps. diff --git a/lib/spring/application_manager.rb b/lib/spring/application_manager.rb index 34c14dac..6ac016d8 100644 --- a/lib/spring/application_manager.rb +++ b/lib/spring/application_manager.rb @@ -126,7 +126,8 @@ def start_wait_thread(pid, child) # as if it does we're no longer interested in the child loop do IO.select([child]) - break if child.recv(1, Socket::MSG_PEEK).empty? + peek = child.recv(1, Socket::MSG_PEEK) + break if peek.nil? || peek.empty? sleep 0.01 end diff --git a/test/support/acceptance_test.rb b/test/support/acceptance_test.rb index 3c47923f..5035bf7f 100644 --- a/test/support/acceptance_test.rb +++ b/test/support/acceptance_test.rb @@ -189,7 +189,7 @@ def self.omg app.insert_into_test "Foo.omg" app.await_reload - assert_failure app.spring_test_command, stdout: "RuntimeError: omg" + assert_failure app.spring_test_command, stdout: "RuntimeError: omg", log: /child \d+ shutdown/ end test "app gets reloaded even with a ton of boot output" do