| require 'socket' | |
| require 'monitor' | |
| require 'common/Params' | |
| require 'common/Logger' | |
| require 'dbgp/CommandHandler' | |
| require 'dbgp/Utils' | |
| require 'debugger/DebugEventHandler' | |
| module XoredDebugger | |
| class DbgpThread | |
| include DebugEventHandler | |
| include XoredDebuggerUtils | |
| include Logger | |
| attr_reader :communicator | |
| def initialize(thread, thread_manager) | |
| @debugger = thread_manager.debugger | |
| @thread = thread | |
| @command_handler = CommandHandler.new(thread_manager, thread) | |
| @exited = false | |
| @context = @debugger.thread_context(thread) | |
| @communicator = Communicator.new(thread) | |
| @monitor = Monitor.new | |
| # starting command handling | |
| log('creating control thread') | |
| @dispatcher = @debugger.create_debug_thread { handle_commands } | |
| end | |
| def exited(exception) | |
| @monitor.synchronize do | |
| begin | |
| send_answer(AbstractContext::STOPPED, exception) | |
| ensure | |
| @exited = true | |
| @communicator.close | |
| end | |
| end | |
| @dispatcher.join | |
| end | |
| def at_breakpoint(context) | |
| end | |
| def at_catchpoint(context, excpt) | |
| end | |
| def at_line(context, file, line) | |
| context.suspend() | |
| @monitor.synchronize do | |
| send_answer(AbstractContext::BREAK) | |
| end | |
| end | |
| def send_answer(status, exception = nil) | |
| unless @unanswered.nil? | |
| response = Response.new(@unanswered) | |
| response.add_attribute('status', status) | |
| if (exception.nil?) | |
| response.add_attribute('reason', 'ok') | |
| else | |
| response.add_attribute('reason', 'exception') | |
| end | |
| @communicator.sendPacket(response) | |
| @unanswered = nil | |
| end | |
| end | |
| def handle_commands | |
| begin | |
| # wait until thread is suspended | |
| while not @context.suspended? | |
| sleep 0.1 | |
| return if @exited | |
| end | |
| log('Started control thread for ' + @thread.object_id.to_s) | |
| params = Params.instance | |
| packet = InitPacket.new(params.key, get_thread_label(@thread), params.script) | |
| @communicator.sendPacket(packet) | |
| while (true) | |
| log('waiting command') | |
| command = @communicator.receive_command | |
| @monitor.synchronize do | |
| log('processing') | |
| response = @command_handler.handle(command) | |
| if (command.name == 'break') | |
| send_answer('break') | |
| end | |
| if (!response.nil?) | |
| @communicator.sendPacket(response) | |
| else | |
| @unanswered = command | |
| end | |
| end | |
| end | |
| rescue SystemExit | |
| # stop command received | |
| rescue IOError | |
| # connection was closed | |
| rescue Exception | |
| logException($!, 'in control thread') unless $!.nil? | |
| ensure | |
| log('Exited control thread for ' + @thread.object_id.to_s) | |
| end | |
| end | |
| end | |
| end |