Details
-
Bug
-
Status: Resolved
-
Normal
-
Resolution: Fixed
-
PUP 7.9.0
-
None
-
Coremunity
-
Coremunity Kanban
-
Needs Assessment
-
Bug Fix
-
Fixes a regression that prevented puppet from running if the current working directory was a short Windows path (8.3)
-
Needs Assessment
Description
Puppet Version: 7.9.0
The autoloader can load the same file twice if the ruby load path contains Windows 8.3 style paths. The file lib/puppet/file_system/uniquefile.rb creates a class whose parent is an anonymous class. If the file is loaded twice, then it will fail with: superclass mismatch for class Uniquefile (TypeError).
To reproduce, install puppet-agent on Windows:
C:\> cmd /c start /w msiexec /qn /i http://builds.puppetlabs.lan/puppet-agent/7.9.0/artifacts/windows/puppet-agent-7.9.0-x64.msi
|
C:\> net stop puppet
|
C:\> cd C:\PROGRA~1\PUPPET~1\Puppet\puppet\bin
|
create "puppettest.rb" containing:
require 'puppet' |
Puppet.initialize_settings
|
puts "RUBYLIBDIR #{RbConfig::CONFIG['rubylibdir']}" |
puts "Loaded Puppet" |
pp $LOADED_FEATURES.grep(/uniquefile/).first |
Puppet::Type.type(:exec) |
And execute the script:
C:\PROGRA~1\PUPPET~1\Puppet\puppet\bin>ruby puppettest.rb
|
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/facter/util/file_helper.rb:9: warning: already initialized constant Class::DEBUG_MESSAGE
|
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/facter/util/file_helper.rb:9: warning: previous definition of DEBUG_MESSAGE was here
|
...
|
Hundreds of already initialized constant errors
|
...
|
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/windows.rb:123: warning: already initialized constant Puppet::FileSystem::Windows::LOCK_VIOLATION
|
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/windows.rb:123: warning: previous definition of LOCK_VIOLATION was here
|
Traceback (most recent call last):
|
33: from puppettest.rb:6:in `<main>'
|
32: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/metatype/manager.rb:154:in `type'
|
31: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/concurrent/lock.rb:10:in `synchronize'
|
30: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/metatype/manager.rb:171:in `block in type'
|
29: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:182:in `load'
|
28: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:78:in `load_file'
|
27: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:78:in `load'
|
26: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/type/exec.rb:1:in `<top (required)>'
|
25: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/type/exec.rb:2:in `<module:Puppet>'
|
24: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/metatype/manager.rb:73:in `newtype'
|
23: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/concurrent/lock.rb:10:in `synchronize'
|
22: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/metatype/manager.rb:126:in `block in newtype'
|
21: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:196:in `loadall'
|
20: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:91:in `loadall'
|
19: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:91:in `each'
|
18: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:93:in `block in loadall'
|
17: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:78:in `load_file'
|
16: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:78:in `load'
|
15: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb:1:in `<top (required)>'
|
14: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb:1:in `require_relative'
|
13: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec.rb:1:in `<top (required)>'
|
12: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec.rb:1:in `require_relative'
|
11: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider.rb:37:in `<top (required)>'
|
10: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider.rb:43:in `<class:Provider>'
|
9: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider.rb:43:in `require_relative'
|
8: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/confiner.rb:1:in `<top (required)>'
|
7: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/confiner.rb:1:in `require_relative'
|
6: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/confine_collection.rb:3:in `<top (required)>'
|
5: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/confine_collection.rb:3:in `require_relative'
|
4: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/confine.rb:3:in `<top (required)>'
|
3: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/confine.rb:3:in `require_relative'
|
2: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util.rb:11:in `<top (required)>'
|
1: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util.rb:11:in `require_relative'
|
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/uniquefile.rb:17:in `<top (required)>': superclass mismatch for class Uniquefile (TypeError)
|
The problem stems from a behavior change in Dir.glob in Ruby 2.1 combined with using relative_require. See PUP-6557 and https://bugs.ruby-lang.org/issues/10819.
When puppet is initially loaded, all LOADED_FEATURES are added using 8.3 paths:
C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/uniquefile.rb
|
When we call `Puppet::Type.type(:exec)`, it uses the autoloader to load the exec type and all of its providers. The autoloader uses `Dir.glob` to find them. Ruby 2.1 changed the behavior of `Dir.glob` to always return the long path name on Windows. So then the autoloader tries to load:
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/uniquefile.rb
|
Also note in the stack trace above how the path changes from 8.3 to long paths:
17: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:78:in `load_file'
|
16: from C:/PROGRA~1/PUPPET~1/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util/autoload.rb:78:in `load'
|
15: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix.rb:1:in `<top (required)>'
|
...
|
1: from C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/util.rb:11:in `require_relative'
|
C:/Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/file_system/uniquefile.rb:17:in `<top (required)>': Could not autoload puppet/type/exec: Could not autoload ../../../../../../../Program Files/Puppet Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/provider/exec/posix: superclass mismatch for class Uniquefile (Puppet::Error)
|