summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMarkus Roberts <Markus@reality.com>2010-07-15 19:44:35 -0700
committerMarkus Roberts <Markus@reality.com>2010-07-18 19:44:15 -0700
commit8c8c1469ae9f1dd11c567d89a27be81653ca2052 (patch)
treed87c89e15e0b390115a53961509a54006344c0d7 /lib
parentd319da41e46f0f3621180d09d3110f67003a7527 (diff)
downloadpuppet-8c8c1469ae9f1dd11c567d89a27be81653ca2052.tar.gz
puppet-8c8c1469ae9f1dd11c567d89a27be81653ca2052.tar.xz
puppet-8c8c1469ae9f1dd11c567d89a27be81653ca2052.zip
Minimal fix for #4243 -- import isn't thread safe
The import function was calling type_loader#import directly so that it could pass in the current file name, but by doing so it was thwarting the thread- safety locking level. This patch rearanges things so that all imports go through the same (thread safe) code path while retaining the current_file passing, error handling, etc. from the old structure.
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/parser/parser_support.rb2
-rw-r--r--lib/puppet/parser/type_loader.rb28
2 files changed, 14 insertions, 16 deletions
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 4f3a4ddff..c0fd37178 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -111,7 +111,7 @@ class Puppet::Parser::Parser
end
def import(file)
- known_resource_types.loader.import(file, @lexer.file)
+ known_resource_types.loader.import_if_possible(file, @lexer.file)
end
def initialize(env)
diff --git a/lib/puppet/parser/type_loader.rb b/lib/puppet/parser/type_loader.rb
index cb8657f0c..c33f90d11 100644
--- a/lib/puppet/parser/type_loader.rb
+++ b/lib/puppet/parser/type_loader.rb
@@ -70,7 +70,7 @@ class Puppet::Parser::TypeLoader
def initialize(env)
self.environment = env
- @loaded = []
+ @loaded = {}
@loading = Helper.new
@imported = {}
@@ -79,10 +79,13 @@ class Puppet::Parser::TypeLoader
def load_until(namespaces, name)
return nil if name == "" # special-case main.
name2files(namespaces, name).each do |filename|
- modname = nil
- import_if_possible(filename) do
- modname = import(filename)
- @loaded << filename
+ modname = begin
+ import_if_possible(filename)
+ rescue Puppet::ImportError => detail
+ # We couldn't load the item
+ # I'm not convienced we should just drop these errors, but this
+ # preserves existing behaviours.
+ nil
end
if result = yield(filename)
Puppet.info "Automatically imported #{name} from #{filename}"
@@ -124,23 +127,18 @@ class Puppet::Parser::TypeLoader
parser.parse
end
- private
-
# Utility method factored out of load for handling thread-safety.
# This isn't tested in the specs, because that's basically impossible.
- def import_if_possible(file, &blk)
- return if @loaded.include?(file)
- begin
+ def import_if_possible(file, current_file = nil)
+ @loaded[file] || begin
case @loading.owner_of(file)
when :this_thread
- return
+ nil
when :another_thread
- return import_if_possible(file, &blk)
+ import_if_possible(file,current_file)
when :nobody
- blk.call
+ @loaded[file] = import(file,current_file)
end
- rescue Puppet::ImportError => detail
- # We couldn't load the item
ensure
@loading.done_with(file)
end