[rubygems/rubygems] Protect specs access at a finer level

https://github.com/rubygems/rubygems/commit/c8cc053bde
This commit is contained in:
David Rodríguez 2021-11-04 13:40:53 +01:00 committed by git
parent 4bc69a25f3
commit 8bdb56fcaf
2 changed files with 12 additions and 16 deletions

View File

@ -67,8 +67,6 @@ class Gem::Installer
@path_warning = false @path_warning = false
@install_lock = Thread::Mutex.new
class << self class << self
# #
# Changes in rubygems to lazily loading `rubygems/command` (in order to # Changes in rubygems to lazily loading `rubygems/command` (in order to
@ -92,12 +90,6 @@ class Gem::Installer
attr_accessor :path_warning attr_accessor :path_warning
##
# Certain aspects of the install process are not thread-safe. This lock is
# used to allow multiple threads to install Gems at the same time.
attr_reader :install_lock
## ##
# Overrides the executable format. # Overrides the executable format.
# #
@ -342,7 +334,7 @@ class Gem::Installer
say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil? say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil?
Gem::Installer.install_lock.synchronize { Gem::Specification.reset } Gem::Specification.reset
run_post_install_hooks run_post_install_hooks
@ -527,7 +519,7 @@ class Gem::Installer
end end
def generate_plugins # :nodoc: def generate_plugins # :nodoc:
latest = Gem::Installer.install_lock.synchronize { Gem::Specification.latest_spec_for(spec.name) } latest = Gem::Specification.latest_spec_for(spec.name)
return if latest && latest.version > spec.version return if latest && latest.version > spec.version
ensure_writable_dir @plugins_dir ensure_writable_dir @plugins_dir

View File

@ -179,14 +179,18 @@ class Gem::Specification < Gem::BasicSpecification
end end
def self.clear_specs # :nodoc: def self.clear_specs # :nodoc:
@@all = nil @@all_specs_mutex.synchronize do
@@stubs = nil @@all = nil
@@stubs_by_name = {} @@stubs = nil
@@spec_with_requirable_file = {} @@stubs_by_name = {}
@@active_stub_with_requirable_file = {} @@spec_with_requirable_file = {}
@@active_stub_with_requirable_file = {}
end
end end
private_class_method :clear_specs private_class_method :clear_specs
@@all_specs_mutex = Thread::Mutex.new
clear_specs clear_specs
# Sentinel object to represent "not found" stubs # Sentinel object to represent "not found" stubs
@ -750,7 +754,7 @@ class Gem::Specification < Gem::BasicSpecification
attr_accessor :specification_version attr_accessor :specification_version
def self._all # :nodoc: def self._all # :nodoc:
@@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec) @@all_specs_mutex.synchronize { @@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec) }
end end
def self.clear_load_cache # :nodoc: def self.clear_load_cache # :nodoc: