From 7a4c9246244c5f49831928424442d803c8e8086d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AA=E3=81=A4=E3=81=8D?= Date: Thu, 15 Sep 2022 14:37:01 +0800 Subject: [PATCH] Make Sprockets::Utils.module_include thread safe --- CHANGELOG.md | 4 ++++ lib/sprockets/utils.rb | 41 +++++++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abd581790..cbfa845a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +**Master** + +* Make `Sprockets::Utils.module_include` thread safe on JRuby. [#760](https://github.com/rails/sprockets/pull/760) + **3.7.2** (June 19, 2018) * Security release for [CVE-2018-3760](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3760). diff --git a/lib/sprockets/utils.rb b/lib/sprockets/utils.rb index 11ff9443e..3f360e04a 100644 --- a/lib/sprockets/utils.rb +++ b/lib/sprockets/utils.rb @@ -147,34 +147,39 @@ def normalize_extension(extension) false end + MODULE_INCLUDE_MUTEX = Mutex.new + private_constant :MODULE_INCLUDE_MUTEX + # Internal: Inject into target module for the duration of the block. # # mod - Module # # Returns result of block. def module_include(base, mod) - old_methods = {} + MODULE_INCLUDE_MUTEX.synchronize do + old_methods = {} - mod.instance_methods.each do |sym| - old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym) - end + mod.instance_methods.each do |sym| + old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym) + end - unless UNBOUND_METHODS_BIND_TO_ANY_OBJECT - base.send(:include, mod) unless base < mod - end + unless UNBOUND_METHODS_BIND_TO_ANY_OBJECT + base.send(:include, mod) unless base < mod + end - mod.instance_methods.each do |sym| - method = mod.instance_method(sym) - base.send(:define_method, sym, method) - end + mod.instance_methods.each do |sym| + method = mod.instance_method(sym) + base.send(:define_method, sym, method) + end - yield - ensure - mod.instance_methods.each do |sym| - base.send(:undef_method, sym) if base.method_defined?(sym) - end - old_methods.each do |sym, method| - base.send(:define_method, sym, method) + yield + ensure + mod.instance_methods.each do |sym| + base.send(:undef_method, sym) if base.method_defined?(sym) + end + old_methods.each do |sym, method| + base.send(:define_method, sym, method) + end end end