Uploaded image for project: 'Puppet'
  1. Puppet
  2. PUP-11184

Autoloader is confused by Windows 8.3 paths

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Ready for Merge
    • Priority: Normal
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: PUP 6.25.0, PUP 7.12.0
    • Component/s: None
    • Labels:
      None
    • Template:
      PUP Bug Template
    • Team:
      Coremunity
    • Sprint:
      Coremunity Kanban
    • Method Found:
      Needs Assessment
    • Release Notes:
      Bug Fix
    • Release Notes Summary:
      Fixes a regression that prevented puppet from running if the current working directory was a short Windows path (8.3)
    • QA Risk Assessment:
      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)
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              josh Josh Cooper
              Reporter:
              josh Josh Cooper
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:

                  Zendesk Support