Merge pull request #7354 from mitchellh/sethvargo/bundler_leak

Fix file leaking in bundler
This commit is contained in:
Seth Vargo 2016-05-28 17:10:06 -04:00
commit 11ed254708
2 changed files with 28 additions and 7 deletions

View File

@ -2,6 +2,7 @@ require "monitor"
require "pathname"
require "set"
require "tempfile"
require "fileutils"
require "bundler"
@ -61,7 +62,7 @@ module Vagrant
end
# Setup the Bundler configuration
@configfile = File.open(Tempfile.new("vagrant").path + "1", "w+")
@configfile = tempfile("vagrant-configfile")
@configfile.close
# Build up the Gemfile for our Bundler context. We make sure to
@ -84,9 +85,13 @@ module Vagrant
# Removes any temporary files created by init
def deinit
File.unlink(ENV["BUNDLE_APP_CONFIG"]) rescue nil
File.unlink(ENV["BUNDLE_CONFIG"]) rescue nil
File.unlink(ENV["GEMFILE"]) rescue nil
# If we weren't enabled, then we don't do anything.
return if !@enabled
FileUtils.rm_rf(ENV["BUNDLE_APP_CONFIG"]) rescue nil
FileUtils.rm_f(ENV["BUNDLE_CONFIG"]) rescue nil
FileUtils.rm_f(ENV["BUNDLE_GEMFILE"]) rescue nil
FileUtils.rm_f(ENV["BUNDLE_GEMFILE"]+".lock") rescue nil
end
# Installs the list of plugins.
@ -181,7 +186,7 @@ module Vagrant
def build_gemfile(plugins)
sources = plugins.values.map { |p| p["sources"] }.flatten.compact.uniq
f = File.open(Tempfile.new("vagrant").path + "2", "w+")
f = tempfile("vagrant-gemfile")
f.tap do |gemfile|
sources.each do |source|
next if source == ""
@ -203,7 +208,6 @@ module Vagrant
gemfile.puts(%Q[gem "#{name}", #{version.inspect}, #{opts.inspect}])
end
gemfile.puts("end")
gemfile.close
end
end
@ -250,11 +254,14 @@ module Vagrant
def with_isolated_gem
raise Errors::BundlerDisabled if !@enabled
tmp_gemfile = tempfile("vagrant-gemfile")
tmp_gemfile.close
# Remove bundler settings so that Bundler isn't loaded when building
# native extensions because it causes all sorts of problems.
old_rubyopt = ENV["RUBYOPT"]
old_gemfile = ENV["BUNDLE_GEMFILE"]
ENV["BUNDLE_GEMFILE"] = Tempfile.new("vagrant-gemfile").path
ENV["BUNDLE_GEMFILE"] = tmp_gemfile.path
ENV["RUBYOPT"] = (ENV["RUBYOPT"] || "").gsub(/-rbundler\/setup\s*/, "")
# Set the GEM_HOME so gems are installed only to our local gem dir
@ -284,6 +291,8 @@ module Vagrant
return yield
end
ensure
tmp_gemfile.unlink rescue nil
ENV["BUNDLE_GEMFILE"] = old_gemfile
ENV["GEM_HOME"] = @gem_home
ENV["RUBYOPT"] = old_rubyopt
@ -293,6 +302,17 @@ module Vagrant
Gem::Specification.all = old_all
end
# This method returns a proper "tempfile" on disk. Ruby's Tempfile class
# would work really great for this, except GC can come along and remove
# the file before we are done with it. This is because we "close" the file,
# but we might be shelling out to a subprocess.
#
# @return [File]
def tempfile(name)
path = Dir::Tmpname.create(name) {}
return File.open(path, "w+")
end
# This is pretty hacky but it is a custom implementation of
# Gem::ConfigFile so that we don't load any gemrc files.
class NilGemConfig < Gem::ConfigFile

View File

@ -55,6 +55,7 @@ module VagrantPlugins
exit_status = env[:ssh_run_exit_status] || 0
return exit_status
else
Vagrant::Bundler.instance.deinit
@logger.debug("Invoking `ssh` action on machine")
vm.action(:ssh, ssh_opts: ssh_opts)