From c832ae8de9205678d67d6750a69b8e2505c63e80 Mon Sep 17 00:00:00 2001 From: Maciej Mensfeld Date: Mon, 21 Nov 2022 12:17:16 +0100 Subject: [PATCH] Make cache and values fully thread-safe Not locking the default initialization can lead to race-conditions. Note: not sure if I should use one or two mutexes as I am not familiar with this code enough to make the judgment. ref: https://github.com/ruby-concurrency/concurrent-ruby/issues/970 --- lib/puppet/settings.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/puppet/settings.rb b/lib/puppet/settings.rb index 7136e742bc1..311e1ac3fb8 100644 --- a/lib/puppet/settings.rb +++ b/lib/puppet/settings.rb @@ -147,8 +147,19 @@ def initialize @configuration_file = nil # And keep a per-environment cache - @cache = Concurrent::Hash.new { |hash, key| hash[key] = Concurrent::Hash.new } - @values = Concurrent::Hash.new { |hash, key| hash[key] = Concurrent::Hash.new } + @mutex = Mutex.new + @cache = Concurrent::Hash.new do |hash, key| + @mutex.synchronize do + break hash[key] if hash.key?(key) + hash[key] = Concurrent::Hash.new + end + end + @values = Concurrent::Hash.new do |hash, key| + @mutex.synchronize do + break hash[key] if hash.key?(key) + hash[key] = Concurrent::Hash.new + end + end # The list of sections we've used. @used = []