| 
									
										
										
										
											2015-04-13 18:02:46 +08:00
										 |  |  | require "fcntl" | 
					
						
							|  |  |  | require "socket" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module Utils | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def self.safe_fork(&_block) | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |     Dir.mktmpdir("homebrew", HOMEBREW_TEMP) do |tmpdir| | 
					
						
							|  |  |  |       UNIXServer.open("#{tmpdir}/socket") do |server| | 
					
						
							|  |  |  |         read, write = IO.pipe | 
					
						
							| 
									
										
										
										
											2015-04-13 18:02:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |         pid = fork do | 
					
						
							|  |  |  |           begin | 
					
						
							| 
									
										
										
										
											2015-04-25 23:22:58 -04:00
										 |  |  |             ENV["HOMEBREW_ERROR_PIPE"] = server.path | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |             server.close | 
					
						
							|  |  |  |             read.close | 
					
						
							|  |  |  |             write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) | 
					
						
							|  |  |  |             yield | 
					
						
							|  |  |  |           rescue Exception => e | 
					
						
							|  |  |  |             Marshal.dump(e, write) | 
					
						
							|  |  |  |             write.close | 
					
						
							| 
									
										
										
										
											2015-04-28 01:39:28 -04:00
										 |  |  |             exit! | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             exit!(true) | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2015-04-13 18:02:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											2015-05-12 21:52:30 -04:00
										 |  |  |             socket.close | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |           end | 
					
						
							|  |  |  |           write.close | 
					
						
							|  |  |  |           data = read.read | 
					
						
							|  |  |  |           read.close | 
					
						
							|  |  |  |           Process.wait(pid) unless socket.nil? | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |           raise Marshal.load(data) unless data.nil? || data.empty? | 
					
						
							| 
									
										
										
										
											2017-06-10 20:12:55 +03:00
										 |  |  |           raise Interrupt if $CHILD_STATUS.exitstatus == 130
 | 
					
						
							| 
									
										
										
										
											2017-08-25 12:35:03 -07:00
										 |  |  |           raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success? | 
					
						
							| 
									
										
										
										
											2015-04-24 22:13:45 -04:00
										 |  |  |         end | 
					
						
							| 
									
										
										
										
											2015-04-13 18:02:46 +08:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |