aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXu Cheng2015-04-13 18:02:46 +0800
committerXu Cheng2015-04-15 19:51:54 +0800
commit436951609d97229fbefc416a7f7796e3519d12f4 (patch)
tree31c07912cc1a2241e11e12a463d386c289699ffe
parent9f0ac075c21f31206a81fcf90b915ea41f69d61a (diff)
downloadhomebrew-436951609d97229fbefc416a7f7796e3519d12f4.tar.bz2
move safe_fork into a standalone method
-rw-r--r--Library/Homebrew/formula_installer.rb47
-rw-r--r--Library/Homebrew/utils.rb1
-rw-r--r--Library/Homebrew/utils/fork.rb44
3 files changed, 50 insertions, 42 deletions
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index c87972d2e..32b61072d 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -11,8 +11,6 @@ require 'install_renamed'
require 'cmd/tap'
require 'hooks/bottles'
require 'debrew'
-require 'fcntl'
-require 'socket'
require 'sandbox'
class FormulaInstaller
@@ -458,9 +456,6 @@ 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
@@ -468,9 +463,6 @@ class FormulaInstaller
# 1. formulae can modify ENV, so we must ensure that each
# installation has a pristine ENV when it starts, forking now is
# the easiest way to do this
- read, write = IO.pipe
- ENV["HOMEBREW_ERROR_PIPE"] = socket_path
-
args = %W[
nice #{RUBY_PATH}
-W0
@@ -480,39 +472,13 @@ class FormulaInstaller
#{formula.path}
].concat(build_argv)
- pid = fork do
- begin
- server.close
- read.close
- write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
- if Sandbox.available? && ARGV.sandbox?
- sandbox = Sandbox.new(formula)
- sandbox.exec(*args)
- else
- exec(*args)
- end
- rescue Exception => e
- Marshal.dump(e, write)
- write.close
- exit! 1
- end
- 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)
+ Utils.safe_fork do
+ if Sandbox.available? && ARGV.sandbox?
+ sandbox = Sandbox.new(formula)
+ sandbox.exec(*args)
else
- socket.send_io(write)
+ exec(*args)
end
- write.close
- data = read.read
- read.close
- 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?
end
raise "Empty installation" if Dir["#{formula.prefix}/*"].empty?
@@ -524,9 +490,6 @@ class FormulaInstaller
formula.rack.rmdir_if_possible
end
raise
- ensure
- server.close
- FileUtils.rm_r File.dirname(socket_path)
end
def link(keg)
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 2cdd920c9..ad358581e 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -4,6 +4,7 @@ require 'os/mac'
require 'utils/json'
require 'utils/inreplace'
require 'utils/popen'
+require 'utils/fork'
require 'open-uri'
class Tty
diff --git a/Library/Homebrew/utils/fork.rb b/Library/Homebrew/utils/fork.rb
new file mode 100644
index 000000000..defe1fa79
--- /dev/null
+++ b/Library/Homebrew/utils/fork.rb
@@ -0,0 +1,44 @@
+require "fcntl"
+require "socket"
+
+module Utils
+ def self.safe_fork(&block)
+ socket_path = "#{Dir.mktmpdir("homebrew", HOMEBREW_TEMP)}/socket"
+ server = UNIXServer.new(socket_path)
+ ENV["HOMEBREW_ERROR_PIPE"] = socket_path
+ read, write = IO.pipe
+
+ pid = fork do
+ begin
+ server.close
+ read.close
+ write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+ yield
+ rescue Exception => e
+ Marshal.dump(e, write)
+ write.close
+ exit! 1
+ end
+ 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) unless socket.nil?
+ raise Marshal.load(data) unless data.nil? or data.empty?
+ raise Interrupt if $?.exitstatus == 130
+ raise "Suspicious failure" unless $?.success?
+ end
+ ensure
+ server.close
+ FileUtils.rm_r File.dirname(socket_path)
+ end
+end