[rubygems/rubygems] Use Monitor#synchronize to ensure to exit

https://github.com/rubygems/rubygems/commit/b424353239
This commit is contained in:
Nobuyoshi Nakada 2023-07-19 22:38:27 +09:00 committed by git
parent f72ddd92be
commit 1b27e7aa1f

View File

@ -36,9 +36,7 @@ module Kernel
def require(path) # :doc: def require(path) # :doc:
return gem_original_require(path) unless Gem.discover_gems_on_require return gem_original_require(path) unless Gem.discover_gems_on_require
begin RUBYGEMS_ACTIVATION_MONITOR.synchronize do
RUBYGEMS_ACTIVATION_MONITOR.enter
path = path.to_path if path.respond_to? :to_path path = path.to_path if path.respond_to? :to_path
if spec = Gem.find_unresolved_default_spec(path) if spec = Gem.find_unresolved_default_spec(path)
@ -49,14 +47,9 @@ module Kernel
Gem.suffixes.each do |s| Gem.suffixes.each do |s|
$LOAD_PATH[0...load_path_check_index].each do |lp| $LOAD_PATH[0...load_path_check_index].each do |lp|
safe_lp = lp.dup.tap(&Gem::UNTAINT) safe_lp = lp.dup.tap(&Gem::UNTAINT)
begin
if File.symlink? safe_lp # for backward compatibility if File.symlink? safe_lp # for backward compatibility
next next
end end
rescue SecurityError
RUBYGEMS_ACTIVATION_MONITOR.exit
raise
end
full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}")) full_path = File.expand_path(File.join(safe_lp, "#{path}#{s}"))
if File.file?(full_path) if File.file?(full_path)
@ -69,20 +62,15 @@ module Kernel
rp rp
end end
begin Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless
Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) resolved_path
rescue StandardError
RUBYGEMS_ACTIVATION_MONITOR.exit
raise
end unless resolved_path
end end
# If there are no unresolved deps, then we can use just try # If there are no unresolved deps, then we can use just try
# normal require handle loading a gem from the rescue below. # normal require handle loading a gem from the rescue below.
if Gem::Specification.unresolved_deps.empty? if Gem::Specification.unresolved_deps.empty?
RUBYGEMS_ACTIVATION_MONITOR.exit next
return gem_original_require(path)
end end
# If +path+ is for a gem that has already been loaded, don't # If +path+ is for a gem that has already been loaded, don't
@ -92,8 +80,7 @@ module Kernel
# TODO request access to the C implementation of this to speed up RubyGems # TODO request access to the C implementation of this to speed up RubyGems
if Gem::Specification.find_active_stub_by_path(path) if Gem::Specification.find_active_stub_by_path(path)
RUBYGEMS_ACTIVATION_MONITOR.exit next
return gem_original_require(path)
end end
# Attempt to find +path+ in any unresolved gems... # Attempt to find +path+ in any unresolved gems...
@ -124,7 +111,6 @@ module Kernel
names = found_specs.map(&:name).uniq names = found_specs.map(&:name).uniq
if names.size > 1 if names.size > 1
RUBYGEMS_ACTIVATION_MONITOR.exit
raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ", "}" raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ", "}"
end end
@ -135,26 +121,20 @@ module Kernel
unless valid unless valid
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate" le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
le.name = names.first le.name = names.first
RUBYGEMS_ACTIVATION_MONITOR.exit
raise le raise le
end end
valid.activate valid.activate
end end
RUBYGEMS_ACTIVATION_MONITOR.exit
gem_original_require(path)
rescue LoadError => load_error
if load_error.path == path
RUBYGEMS_ACTIVATION_MONITOR.enter
begin
require_again = Gem.try_activate(path)
ensure
RUBYGEMS_ACTIVATION_MONITOR.exit
end end
return gem_original_require(path) if require_again begin
gem_original_require(path)
rescue LoadError => load_error
if load_error.path == path &&
RUBYGEMS_ACTIVATION_MONITOR.synchronize { Gem.try_activate(path) }
return gem_original_require(path)
end end
raise load_error raise load_error