From 4f4f8a705a8e713bceee8cacca52e9bce22e28dc Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Wed, 18 Dec 2019 19:00:29 +0900 Subject: [PATCH] Make `LoadInterlockAwareMonitor` work in Ruby 2.7 Currently `LoadInterlockAwareMonitorTest` does not pass with Ruby 2.7 [1]. This is due to the refactoring of the `monitor` done in Ruby 2.7 [2]. With this refactoring, the behavior of the method has changed from the expected behavior in `LoadInterlockAwareMonitor`. This patch also overwrites `synchronize` so that `LoadInterlockAwareMonitor` works as expected. [1]: https://buildkite.com/rails/rails/builds/65877#eec47af5-7595-47cb-97c0-30c589716176/996-2743 [2]: https://bugs.ruby-lang.org/issues/16255 --- .../load_interlock_aware_monitor.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor.rb b/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor.rb index a8455c0048..480c34c640 100644 --- a/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor.rb +++ b/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor.rb @@ -7,11 +7,29 @@ module ActiveSupport # A monitor that will permit dependency loading while blocked waiting for # the lock. class LoadInterlockAwareMonitor < Monitor + EXCEPTION_NEVER = { Exception => :never }.freeze + EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze + private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE + # Enters an exclusive section, but allows dependency loading while blocked def mon_enter mon_try_enter || ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super } end + + def synchronize + Thread.handle_interrupt(EXCEPTION_NEVER) do + mon_enter + + begin + Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do + yield + end + ensure + mon_exit + end + end + end end end end