| 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 |