summaryrefslogtreecommitdiff
path: root/lib/rubygems/installer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems/installer.rb')
-rw-r--r--lib/rubygems/installer.rb19
1 files changed, 15 insertions, 4 deletions
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 939bc9693d..0ccf7ad52f 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -9,6 +9,7 @@ require 'rubygems/package'
require 'rubygems/ext'
require 'rubygems/user_interaction'
require 'fileutils'
+require 'thread'
##
# The installer installs the files contained in the .gem into the Gem.home.
@@ -32,6 +33,14 @@ class Gem::Installer
ENV_PATHS = %w[/usr/bin/env /bin/env]
##
+ # The builder shells-out to run various commands after changing the
+ # directory. This means multiple installations cannot be allowed to build
+ # extensions in parallel as they may change each other's directories leading
+ # to broken extensions or failed installations.
+
+ CHDIR_MUTEX = Mutex.new # :nodoc:
+
+ ##
# Raised when there is an error while building extensions.
#
class ExtensionBuildError < Gem::InstallError; end
@@ -675,11 +684,13 @@ TEXT
begin
FileUtils.mkdir_p dest_path
- Dir.chdir extension_dir do
- results = builder.build(extension, gem_dir, dest_path,
- results, @build_args)
+ CHDIR_MUTEX.synchronize do
+ Dir.chdir extension_dir do
+ results = builder.build(extension, gem_dir, dest_path,
+ results, @build_args)
- say results.join("\n") if Gem.configuration.really_verbose
+ say results.join("\n") if Gem.configuration.really_verbose
+ end
end
rescue
extension_build_error(extension_dir, results.join("\n"), $@)