aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/build.rb3
-rw-r--r--Library/Homebrew/formula_installer.rb27
2 files changed, 21 insertions, 9 deletions
diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb
index f45dead83..fd0fc05b1 100644
--- a/Library/Homebrew/build.rb
+++ b/Library/Homebrew/build.rb
@@ -10,6 +10,7 @@ require "keg"
require "extend/ENV"
require "debrew"
require "fcntl"
+require "socket"
class Build
attr_reader :formula, :deps, :reqs
@@ -172,7 +173,7 @@ class Build
end
begin
- error_pipe = IO.new(ENV["HOMEBREW_ERROR_PIPE"].to_i, "w")
+ error_pipe = UNIXSocket.open(ENV["HOMEBREW_ERROR_PIPE"], &:recv_io)
error_pipe.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
# Invalidate the current sudo timestamp in case a build script calls sudo
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 515239da7..38bf16996 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -11,6 +11,8 @@ require 'install_renamed'
require 'cmd/tap'
require 'hooks/bottles'
require 'debrew'
+require 'fcntl'
+require 'socket'
class FormulaInstaller
include FormulaCellarChecks
@@ -455,6 +457,9 @@ class FormulaInstaller
end
def build
+ socket_path = "#{Dir.mktmpdir("homebrew", HOMEBREW_TEMP)}/socket"
+ server = UNIXServer.new(socket_path)
+
FileUtils.rm Dir["#{HOMEBREW_LOGS}/#{formula.name}/*"]
@start_time = Time.now
@@ -463,8 +468,7 @@ class FormulaInstaller
# installation has a pristine ENV when it starts, forking now is
# the easiest way to do this
read, write = IO.pipe
- # I'm guessing this is not a good way to do this, but I'm no UNIX guru
- ENV['HOMEBREW_ERROR_PIPE'] = write.to_i.to_s
+ ENV["HOMEBREW_ERROR_PIPE"] = socket_path
args = %W[
nice #{RUBY_PATH}
@@ -475,14 +479,11 @@ class FormulaInstaller
#{formula.path}
].concat(build_argv)
- # Ruby 2.0+ sets close-on-exec on all file descriptors except for
- # 0, 1, and 2 by default, so we have to specify that we want the pipe
- # to remain open in the child process.
- args << { write => write } if RUBY_VERSION >= "2.0"
-
pid = fork do
begin
+ server.close
read.close
+ write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
exec(*args)
rescue Exception => e
Marshal.dump(e, write)
@@ -492,10 +493,17 @@ class FormulaInstaller
end
ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back
+ begin
+ socket = server.accept_nonblock
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ retry unless Process.waitpid(pid, Process::WNOHANG)
+ else
+ socket.send_io(write)
+ end
write.close
data = read.read
read.close
- Process.wait(pid)
+ Process.wait(pid) unless socket.nil?
raise Marshal.load(data) unless data.nil? or data.empty?
raise Interrupt if $?.exitstatus == 130
raise "Suspicious installation failure" unless $?.success?
@@ -510,6 +518,9 @@ class FormulaInstaller
formula.rack.rmdir_if_possible
end
raise
+ ensure
+ server.close
+ FileUtils.rm_r File.dirname(socket_path)
end
def link(keg)