diff options
| author | Xu Cheng | 2015-04-13 18:02:46 +0800 |
|---|---|---|
| committer | Xu Cheng | 2015-04-15 19:51:54 +0800 |
| commit | 06f72ab38f7330eaef9a4cc05dd31b35e8bf26f5 (patch) | |
| tree | 1beb8858448723e7eba52bcc5ec04b3dde7c784a /Library/Homebrew/utils | |
| parent | c952fda20230db91aae369423475757a0fc8db71 (diff) | |
| download | brew-06f72ab38f7330eaef9a4cc05dd31b35e8bf26f5.tar.bz2 | |
move safe_fork into a standalone method
Diffstat (limited to 'Library/Homebrew/utils')
| -rw-r--r-- | Library/Homebrew/utils/fork.rb | 44 |
1 files changed, 44 insertions, 0 deletions
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 |
