module DebuggerXml::MultiProcess

Public Class Methods

create_mp_exec(private=false) click to toggle source
# File lib/debugger_xml/multiprocess/monkey.rb, line 19
def self.create_mp_exec(private=false)
  %Q{
    alias pre_debugger_exec exec

    #{private ? "private" : ""}
    def exec(*args)
      Debugger.handler.interface.close
      pre_debugger_exec(*args)
    end
  }
end
create_mp_fork(private=false) click to toggle source
# File lib/debugger_xml/multiprocess/monkey.rb, line 3
def self.create_mp_fork(private=false)
  %Q{
    alias pre_debugger_fork fork

    #{private ? "private" : ""}
    def fork(*args)
      if block_given?
        return pre_debugger_fork{DebuggerXml::MultiProcess::pre_child; yield}
      end
      result = pre_debugger_fork
      DebuggerXml::MultiProcess::pre_child unless result
      result
    end
  }
end
find_free_port(host) click to toggle source
# File lib/debugger_xml/multiprocess/pre_child.rb, line 71
def find_free_port(host)
  server = TCPServer.open(host, 0)
  port   = server.addr[1]
  server.close
  port
end
pre_child() click to toggle source
# File lib/debugger_xml/multiprocess/pre_child.rb, line 4
def pre_child
  return unless ENV['IDE_PROCESS_DISPATCHER']

  require 'socket'
  require 'ostruct'

  host = ENV['DEBUGGER_HOST']
  port = find_free_port(host)

  options = OpenStruct.new(
    host: host,
    port: port,
    stop: false,
    tracing: false,
    wait_for_start: true,
    int_handler: true,
    debug_mode: (ENV['DEBUGGER_DEBUG_MODE'] == 'true'),
    dispatcher_port: ENV['IDE_PROCESS_DISPATCHER']
  )

  acceptor_host, acceptor_port = ENV['IDE_PROCESS_DISPATCHER'].split(":")
  acceptor_host, acceptor_port = '127.0.0.1', acceptor_host unless acceptor_port

  connected = false
  3.times do |i|
    begin
      s = TCPSocket.open(acceptor_host, acceptor_port)
      s.print(port)
      s.close
      connected = true
      start_debugger(options)
      return
    rescue => bt
      $stderr.puts "#{Process.pid}: connection failed(#{i+1})"
      $stderr.puts "Exception: #{bt}"
      $stderr.puts bt.backtrace.map { |l| "\t#{l}" }.join("\n")
      sleep 0.3
    end unless connected
  end
end
start_debugger(options) click to toggle source
# File lib/debugger_xml/multiprocess/pre_child.rb, line 45
def start_debugger(options)
  if Debugger.started?
    # we're in forked child, only need to restart control thread
    Debugger.breakpoints.clear
    Debugger.control_thread = nil
  end

  if options.int_handler
    # install interruption handler
    trap('INT') { Debugger.interrupt_last }
  end

  # set options
  Debugger.tracing = options.tracing
  Debugger.wait_for_start = options.wait_for_start
  Debugger.wait_connection = true
  Debugger.printer = Printers::Xml.new
  DebuggerXml.logger = if options.debug_mode
    Debugger::Xml::Ide::Logger.new
  else
    Debugger::Xml::FakeLogger.new
  end
  DebuggerXml.start_remote_ide(options.host, options.port)
end