PageRenderTime 63ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ruby-debug-ide.rb

https://github.com/mark-moseley/ruby-debug-ide
Ruby | 184 lines | 139 code | 29 blank | 16 comment | 8 complexity | cd59424600bf34a32d180cf58b8062ad MD5 | raw file
  1. require 'pp'
  2. require 'stringio'
  3. require "socket"
  4. require 'thread'
  5. require 'ruby-debug-base'
  6. if RUBY_VERSION < "1.9"
  7. require 'ruby-debug/xml_printer'
  8. require 'ruby-debug/processor'
  9. require 'ruby-debug/event_processor'
  10. else
  11. require_relative 'ruby-debug/xml_printer'
  12. require_relative 'ruby-debug/processor'
  13. require_relative 'ruby-debug/event_processor'
  14. end
  15. module Debugger
  16. class << self
  17. # Prints to the stderr using printf(*args) if debug logging flag (-d) is on.
  18. def print_debug(*args)
  19. if Debugger.cli_debug
  20. $stderr.printf(*args)
  21. $stderr.printf("\n")
  22. $stderr.flush
  23. end
  24. end
  25. def without_stderr
  26. begin
  27. if RUBY_PLATFORM =~ /(win32|mingw32)/
  28. $stderr = File.open('NUL', 'w')
  29. else
  30. $stderr = File.open('/dev/null', 'w')
  31. end
  32. yield
  33. ensure
  34. $stderr = STDERR
  35. end
  36. end
  37. end
  38. class Context
  39. def interrupt
  40. self.stop_next = 1
  41. end
  42. private
  43. def event_processor
  44. Debugger.event_processor
  45. end
  46. def at_breakpoint(breakpoint)
  47. event_processor.at_breakpoint(self, breakpoint)
  48. end
  49. def at_catchpoint(excpt)
  50. event_processor.at_catchpoint(self, excpt)
  51. end
  52. def at_tracing(file, line)
  53. if event_processor
  54. event_processor.at_tracing(self, file, line)
  55. else
  56. Debugger::print_debug "trace: location=\"%s:%s\", threadId=%d", file, line, self.thnum
  57. end
  58. end
  59. def at_line(file, line)
  60. event_processor.at_line(self, file, line)
  61. end
  62. def at_return(file, line)
  63. event_processor.at_return(self, file, line)
  64. end
  65. end
  66. class << self
  67. attr_accessor :event_processor, :cli_debug, :xml_debug
  68. attr_reader :control_thread
  69. #
  70. # Interrupts the current thread
  71. #
  72. def interrupt
  73. current_context.interrupt
  74. end
  75. #
  76. # Interrupts the last debugged thread
  77. #
  78. def interrupt_last
  79. skip do
  80. if context = last_context
  81. return nil unless context.thread.alive?
  82. context.interrupt
  83. end
  84. context
  85. end
  86. end
  87. def start_server(host = nil, port = 1234)
  88. start
  89. start_control(host, port)
  90. end
  91. def debug_program(options)
  92. start_server(options.host, options.port)
  93. raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive?
  94. @mutex = Mutex.new
  95. @proceed = ConditionVariable.new
  96. # wait for 'start' command
  97. @mutex.synchronize do
  98. @proceed.wait(@mutex)
  99. end
  100. bt = debug_load(Debugger::PROG_SCRIPT, options.stop, options.load_mode)
  101. if bt
  102. $stderr.print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n"
  103. $stderr.print "Uncaught exception: #{bt}\n"
  104. end
  105. end
  106. def run_prog_script
  107. return unless @mutex
  108. @mutex.synchronize do
  109. @proceed.signal
  110. end
  111. end
  112. def start_control(host, port)
  113. return if @control_thread
  114. @control_thread = DebugThread.new do
  115. begin
  116. $stderr.printf "Fast Debugger (ruby-debug-ide 0.4.9) listens on #{host}:#{port}\n"
  117. # 127.0.0.1 seemingly works with all systems and with IPv6 as well.
  118. # "localhost" and nil on have problems on some systems.
  119. host ||= '127.0.0.1'
  120. server = TCPServer.new(host, port)
  121. while (session = server.accept)
  122. begin
  123. interface = RemoteInterface.new(session)
  124. @event_processor = EventProcessor.new(interface)
  125. ControlCommandProcessor.new(interface).process_commands
  126. rescue StandardError, ScriptError => ex
  127. $stderr.printf "Exception in DebugThread loop: #{ex}\n"
  128. exit 1
  129. end
  130. end
  131. rescue
  132. $stderr.printf "Exception in DebugThread: #$!\n"
  133. exit 2
  134. end
  135. end
  136. end
  137. end
  138. class Exception # :nodoc:
  139. attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
  140. end
  141. module Kernel
  142. #
  143. # Stops the current thread after a number of _steps_ made.
  144. #
  145. def debugger(steps = 1)
  146. Debugger.current_context.stop_next = steps
  147. end
  148. #
  149. # Returns a binding of n-th call frame
  150. #
  151. def binding_n(n = 0)
  152. Debugger.current_context.frame_binding[n+1]
  153. end
  154. end
  155. end