From 4fb6f0b2ec5e59b01e55a052e7c9bfb274b884df Mon Sep 17 00:00:00 2001 From: Nick LaMuro Date: Wed, 17 Jan 2018 15:37:07 -0600 Subject: [PATCH] Fix memory leak with ruby/require/autoload_paths In ruby versions less than 2.5.0, it was found that if you have Pathname objects in the $LOAD_PATH instead of regular strings, it messes with ruby's internals and causes a memory leak. In most ruby applications, this wouldn't be much of an issue, but there are a significant number of deferred require statements that we do in manageiq that cause this to leak overtime. Further more, this seems to be an issue that presents itself even if the file has been loaded previously (mostly a no-op for require). Replication of this issue can be done using a simple ruby script: require 'pathname' require 'fileutils' puts Process.pid Dir.mkdir("foo") unless Dir.exists?("foo") $LOAD_PATH.unshift(Pathname.new("foo")) FileUtils.touch("empty.rb") 1500.times { 1500.times { require "empty" }; print "."; GC.start; } By simply running the application with the Pathnames converted to strings, this should be a proper and low cost workaround for us until it is patched in ruby or we update manageiq to >= ruby 2.5.0. --- config/application.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/config/application.rb b/config/application.rb index caacdc1dbac..d723cf79c90 100644 --- a/config/application.rb +++ b/config/application.rb @@ -90,15 +90,15 @@ class Application < Rails::Application # Customize any additional options below... config.autoload_paths += config.eager_load_paths - config.autoload_paths << Rails.root.join("app", "models", "aliases") - config.autoload_paths << Rails.root.join("app", "models", "mixins") - config.autoload_paths << Rails.root.join("lib", "miq_automation_engine", "models") - config.autoload_paths << Rails.root.join("lib", "miq_automation_engine", "models", "mixins") - config.autoload_paths << Rails.root.join("app", "controllers", "mixins") - config.autoload_paths << Rails.root.join("lib") - config.autoload_paths << Rails.root.join("lib", "services") - - config.autoload_once_paths << Rails.root.join("lib", "vmdb", "console_methods.rb") + config.autoload_paths << Rails.root.join("app", "models", "aliases").to_s + config.autoload_paths << Rails.root.join("app", "models", "mixins").to_s + config.autoload_paths << Rails.root.join("lib", "miq_automation_engine", "models").to_s + config.autoload_paths << Rails.root.join("lib", "miq_automation_engine", "models", "mixins").to_s + config.autoload_paths << Rails.root.join("app", "controllers", "mixins").to_s + config.autoload_paths << Rails.root.join("lib").to_s + config.autoload_paths << Rails.root.join("lib", "services").to_s + + config.autoload_once_paths << Rails.root.join("lib", "vmdb", "console_methods.rb").to_s # config.eager_load_paths accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. # Defaults to every folder in the app directory of the application.