| ############################################################################### |
| # Copyright (c) 2005, 2007 IBM Corporation and others. |
| # All rights reserved. This program and the accompanying materials |
| # are made available under the terms of the Eclipse Public License v1.0 |
| # which accompanies this distribution, and is available at |
| # http://www.eclipse.org/legal/epl-v10.html |
| # |
| |
| ############################################################################### |
| |
| require 'cgi' |
| require 'thread' |
| |
| |
| require 'dbgp/command' |
| require 'dbgp/socket_io' |
| require 'dbgp/test_io' |
| require 'dbgp/printer' |
| require 'dbgp/capturer' |
| require 'dbgp/ruby_thread' |
| require 'dbgp/ruby_breakpoints' |
| |
| module XoredDebugger |
| |
| class RubyDebugger |
| private |
| def add_thread(thread) |
| @logger.puts('Adding thread: ' + thread.to_s) |
| |
| printer = Printer.new |
| |
| io = @test ? TestIO.new(@logger, printer) : SocketIO.new(@host, @port, @logger, printer) |
| |
| @threads[thread] = RubyThread.new(self, thread, io, @key) |
| end |
| |
| def remove_thread(thread) |
| @logger.puts('Removing thread: ' + thread.to_s) |
| @threads[thread].terminate |
| @threads.delete(thread) |
| end |
| |
| def thread_list |
| Thread.list - [@remover] |
| end |
| |
| def add_threads |
| @mutex.synchronize do |
| added = thread_list - @threads.keys |
| added.each { |t| |
| add_thread(t) |
| } |
| end |
| end |
| |
| def remove_threads |
| @mutex.synchronize do |
| @threads.each { |t, thread| |
| if thread.terminated? |
| Thread.kill(t) |
| end |
| } |
| |
| removed = @threads.keys - thread_list |
| removed.each { |t| |
| remove_thread(t) |
| } |
| end |
| end |
| |
| public |
| def initialize(host, port, key, logger, test) |
| @host = host |
| @port = port |
| @key = key |
| @logger = logger |
| @test = test |
| |
| @threads = {} |
| |
| @stdout_capturer = StdoutCapturer.new(true) |
| #@stderr_capturer = StderrCapturer.new(true) |
| |
| @breakpoints = Breakpoints.new |
| @mutex = Mutex.new |
| |
| @remover = Thread.new do |
| loop do |
| remove_threads |
| sleep 0.5 |
| end |
| end |
| end |
| |
| def terminate |
| @logger.puts('Debugger termination...') |
| Thread.kill(@remover) |
| |
| @mutex.synchronize do |
| @threads.each { |thread, t| |
| t.terminate |
| } |
| end |
| end |
| |
| def breakpoints |
| @breakpoints |
| end |
| |
| def logger |
| @logger |
| end |
| |
| def capturer |
| @stdout_capturer |
| end |
| |
| # Logging |
| def log(text) |
| @logger.puts(text) |
| end |
| |
| # Test mode |
| def test? |
| @test |
| end |
| |
| # Tracing |
| def trace(event, file, line, id, binding, klass) |
| if Thread.current == @remover |
| return |
| end |
| |
| add_threads |
| thread = @threads[Thread.current] |
| thread.trace(event, file, line, id, binding, klass) |
| end |
| end # class RubyDebugger |
| |
| end # module |