From 659a9bdee33b7c5ad7981b0aac62dfbd6d407af8 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Sat, 26 Jan 2013 16:19:47 +0400 Subject: [PATCH 001/302] fix string encoding issues --- lib/ruby-debug-ide/commands/variables.rb | 2 ++ lib/ruby-debug-ide/version.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 22 ++++++++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index b0b1cdc..c07e452 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -79,6 +79,8 @@ def execute print_array(obj) elsif (obj.is_a?(Hash)) then print_hash(obj) + elsif (obj.is_a?(String)) + print_string(obj) else print_element("variables") do # instance variables diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 8373aa7..232fcad 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.17.beta14' + IDE_VERSION='0.4.17.beta16' end \ No newline at end of file diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 56c2b09..3706f9c 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -127,6 +127,13 @@ def print_hash(hash) } end end + + def print_string(string) + print_element("variables") do + print_variable('bytes', string.bytes.to_a, 'instance') if string.respond_to?('bytes') + print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding') + end + end def print_variable(name, value, kind) name = name.to_s @@ -141,13 +148,20 @@ def print_variable(name, value, kind) else value_str = "#{value.class} (#{value.size} element(s))" end - else + elsif value.is_a?(String) + has_children = value.respond_to?('bytes') || value.respond_to?('encoding') + value_str = value + else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #$!>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end end + + if value_str.respond_to?('encode') + value_str = value_str.encode("UTF-8") + end value_str = "[Binary Data]" if (value_str.respond_to?('is_binary_data?') && value_str.is_binary_data?) print("", CGI.escapeHTML(name), kind, CGI.escapeHTML(value_str), value.class, @@ -256,12 +270,12 @@ def print_at_line(context, file, line) end def print_exception(exception, binding) - print_variables(%w(error), 'exception') do |var| + print_element("variables") do proxy = ExceptionProxy.new(exception) InspectCommand.reference_result(proxy) - proxy + print_variable('error', proxy, 'exception') end - rescue + rescue Exception => e print "", exception.class, CGI.escapeHTML(exception.to_s) end From 86a5a103af512fb52c73dd4dbf7e4820e299677b Mon Sep 17 00:00:00 2001 From: Nelson Chen Date: Tue, 5 Mar 2013 22:07:49 -0800 Subject: [PATCH 002/302] Update ruby-debug-ide.gemspec Correct Homepage URL --- ruby-debug-ide.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruby-debug-ide.gemspec b/ruby-debug-ide.gemspec index 8bfcdec..3fa468d 100644 --- a/ruby-debug-ide.gemspec +++ b/ruby-debug-ide.gemspec @@ -22,7 +22,7 @@ end Gem::Specification.new do |spec| spec.name = "ruby-debug-ide" - spec.homepage = "https://github.com/JetBrains/ruby-debug-ide" + spec.homepage = "https://github.com/ruby-debug/ruby-debug-ide" spec.summary = "IDE interface for ruby-debug." spec.description = <<-EOF An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine. @@ -47,4 +47,4 @@ EOF # rdoc spec.has_rdoc = false -end \ No newline at end of file +end From e3aac51df4c98db00af479fc9536400ec33187b6 Mon Sep 17 00:00:00 2001 From: Payam Hekmat Date: Mon, 1 Apr 2013 20:52:54 -0500 Subject: [PATCH 003/302] Fix debugging of a forking process that's run on a remote machine --- lib/ruby-debug-ide.rb | 29 ++++++++++---------- lib/ruby-debug-ide/multiprocess/pre_child.rb | 26 +++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index cb6ad76..0fbbc2b 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -6,7 +6,7 @@ require 'ruby-debug-base' else require 'debase' -end +end require 'ruby-debug-ide/version' require 'ruby-debug-ide/xml_printer' @@ -14,7 +14,7 @@ require 'ruby-debug-ide/event_processor' module Debugger - + class << self # Prints to the stderr using printf(*args) if debug logging flag (-d) is on. def print_debug(*args) @@ -25,7 +25,7 @@ def print_debug(*args) $stderr.flush end end - + def cleanup_backtrace(backtrace) cleared = [] return cleared unless backtrace @@ -40,12 +40,12 @@ def cleanup_backtrace(backtrace) end cleared end - + attr_accessor :cli_debug, :xml_debug attr_accessor :control_thread attr_reader :interface - + # # Interrupts the last debugged thread # @@ -69,10 +69,10 @@ def prepare_debugger(options) start_server(options.host, options.port) raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive? - + @mutex = Mutex.new @proceed = ConditionVariable.new - + # wait for 'start' command @mutex.synchronize do @proceed.wait(@mutex) @@ -89,14 +89,14 @@ def debug_program(options) $stderr.print Debugger.cleanup_backtrace(bt.backtrace).map{|l| "\t#{l}"}.join("\n"), "\n" end end - + def run_prog_script return unless @mutex @mutex.synchronize do @proceed.signal end end - + def start_control(host, port) raise "Debugger is not started" unless started? return if @control_thread @@ -110,11 +110,12 @@ def start_control(host, port) $stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{gem_name} #{VERSION}) listens on #{host}:#{port}\n" server = TCPServer.new(host, port) while (session = server.accept) - $stderr.puts "Connected from #{session.addr[2]}" if Debugger.cli_debug + $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug dispatcher = ENV['IDE_PROCESS_DISPATCHER'] if (dispatcher) - ENV['IDE_PROCESS_DISPATCHER'] = "#{session.addr[2]}:#{dispatcher}" unless dispatcher.include?(":") - end + ENV['IDE_PROCESS_DISPATCHER'] = "#{session.peeraddr[2]}:#{dispatcher}" unless dispatcher.include?(":") + ENV['DEBUGGER_HOST'] = host + end begin @interface = RemoteInterface.new(session) self.handler = EventProcessor.new(interface) @@ -132,9 +133,9 @@ def start_control(host, port) end end end - + end - + class Exception # :nodoc: attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context end diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 18bb5f9..9cc89a4 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -5,10 +5,10 @@ def pre_child require "socket" require "ostruct" - - host = '127.0.0.1' + + host = ENV['DEBUGGER_HOST'] port = find_free_port(host) - + options = OpenStruct.new( 'frame_bind' => false, 'host' => host, @@ -18,10 +18,10 @@ def pre_child 'tracing' => false, 'int_handler' => true ) - + 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 @@ -39,28 +39,28 @@ def pre_child end unless connected end end - + def start_debugger(options) if Debugger.started? #we're in forked child, only need to restart control thread - Debugger.breakpoints.clear + Debugger.breakpoints.clear Debugger.control_thread = nil Debugger.start_control(options.host, options.port) end - + if options.int_handler # install interruption handler trap('INT') { Debugger.interrupt_last } end - + # set options Debugger.keep_frame_binding = options.frame_bind - Debugger.tracing = options.tracing - + Debugger.tracing = options.tracing + Debugger.prepare_debugger(options) end - - + + def find_free_port(host) server = TCPServer.open(host, 0) port = server.addr[1] From 391e6602cd91695cb16475855928c3ebe0228787 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 12 Apr 2013 14:03:00 +0400 Subject: [PATCH 004/302] don't fail when cannot encode string to UTF8 --- lib/ruby-debug-ide/xml_printer.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 3706f9c..abc1b37 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -160,7 +160,10 @@ def print_variable(name, value, kind) end if value_str.respond_to?('encode') + begin value_str = value_str.encode("UTF-8") + rescue + end end value_str = "[Binary Data]" if (value_str.respond_to?('is_binary_data?') && value_str.is_binary_data?) print("", From 477c3c590aec9a1d25b38089cb98030db5264ad1 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 3 Jun 2013 20:27:51 +0400 Subject: [PATCH 005/302] do not filter out debase path in subprocesses --- lib/ruby-debug-ide/multiprocess/starter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/multiprocess/starter.rb b/lib/ruby-debug-ide/multiprocess/starter.rb index 8b557e1..f8435e4 100644 --- a/lib/ruby-debug-ide/multiprocess/starter.rb +++ b/lib/ruby-debug-ide/multiprocess/starter.rb @@ -1,7 +1,7 @@ if ENV['IDE_PROCESS_DISPATCHER'] require 'rubygems' ENV['DEBUGGER_STORED_RUBYLIB'].split(File::PATH_SEPARATOR).each do |path| - next unless path =~ /ruby-debug-ide|ruby-debug-base|linecache/ + next unless path =~ /ruby-debug-ide|ruby-debug-base|linecache|debase/ $LOAD_PATH << path end require 'ruby-debug-ide' From 9e0385edb4ef1e7a3167af5e76d43d5038fc9a15 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 3 Jun 2013 20:51:36 +0400 Subject: [PATCH 006/302] fixed install check, added debase installation for 2.0 --- ext/mkrf_conf.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/mkrf_conf.rb b/ext/mkrf_conf.rb index cbb626e..14a9989 100644 --- a/ext/mkrf_conf.rb +++ b/ext/mkrf_conf.rb @@ -1,8 +1,8 @@ jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE) def already_installed(dep) - Gem::DependencyInstaller.new(:domain => :local).find_gems_with_sources(dep) || - Gem::DependencyInstaller.new(:domain => :local,:prerelease => true).find_gems_with_sources(dep) + !Gem::DependencyInstaller.new(:domain => :local).find_gems_with_sources(dep).empty? || + !Gem::DependencyInstaller.new(:domain => :local,:prerelease => true).find_gems_with_sources(dep).empty? end unless jruby @@ -21,7 +21,7 @@ def already_installed(dep) elsif RUBY_VERSION < '2.0' dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.24') else - # dep = Gem::Dependency.new("debase", '> 0') + dep = Gem::Dependency.new("debase", '> 0') end begin From dcefde9f464f64132e3bc03b129840c4b3061330 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 3 Jun 2013 20:52:15 +0400 Subject: [PATCH 007/302] 0.4.17 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 232fcad..47e0052 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.17.beta16' + IDE_VERSION='0.4.17' end \ No newline at end of file From abd9f822788081445be1d0b5e1dde40bb0e4440a Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 11 Jul 2013 15:51:04 +0400 Subject: [PATCH 008/302] we always should load ruby-debug-base for JRuby this change fix first problem we have with debugging JRuby with language level 2.0. But after that I've got the following exception which means ruby-debug-base should also be patched for this language level. Util.java:122:in `typeForEvent': java.lang.IllegalArgumentException: unknown event type: b-return from DebugEventHook.java:97:in `eventHandler' from EventHook.java:30:in `event' from Ruby.java:2882:in `callEventHooks' from ThreadContext.java:629:in `trace' from ThreadContext.java:625:in `trace' from ASTInterpreter.java:140:in `blockPostTrace' from ASTInterpreter.java:114:in `INTERPRET_BLOCK' from Interpreted19Block.java:206:in `evalBlockBody' from Interpreted19Block.java:194:in `yield' from Interpreted19Block.java:125:in `call' from Block.java:101:in `call' from RubyProc.java:274:in `call' from RubyProc.java:215:in `call' from Ruby.java:2973:in `tearDown' from Ruby.java:2957:in `tearDown' from Main.java:282:in `internalRun' from Main.java:221:in `run' from Main.java:201:in `main' --- lib/ruby-debug-ide.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 0fbbc2b..6134f3c 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -2,7 +2,7 @@ require 'stringio' require "socket" require 'thread' -if (RUBY_VERSION < '2.0') +if (RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION)) require 'ruby-debug-base' else require 'debase' From 0360e60a5e8ecf9c830967174b0c5e11b6f012c1 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 29 Jul 2013 15:05:40 +0400 Subject: [PATCH 009/302] version bump --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 47e0052..d52753c 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.17' + IDE_VERSION='0.4.18' end \ No newline at end of file From cf0f0a616b4f5f4b9853e7b0bca669c46b03ab8f Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 28 Aug 2013 15:18:53 +0400 Subject: [PATCH 010/302] use ::Kernel.binding, not just any binding method out there --- lib/ruby-debug-ide/commands/variables.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index c07e452..ba53b6f 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -86,7 +86,7 @@ def execute # instance variables kind = 'instance' inst_vars = obj.instance_variables - instance_binding = obj.instance_eval{binding()} + instance_binding = obj.instance_eval{::Kernel.binding()} # print self at top position print_variable('self', debug_eval('self', instance_binding), kind) if inst_vars.include?('self') inst_vars.sort.each do |var| @@ -94,7 +94,7 @@ def execute end # class variables - class_binding = obj.class.class_eval('binding()') + class_binding = obj.class.class_eval('::Kernel.binding()') obj.class.class_variables.sort.each do |var| print_variable(var, debug_eval(var, class_binding), 'class') end From 9ff8728c24d0e1bd4b7670ad18dc77c12c89ee43 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 28 Aug 2013 15:19:58 +0400 Subject: [PATCH 011/302] rely on base bindings, it can create locals-only bindings just fine --- lib/ruby-debug-ide/command.rb | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 24a970e..2c76632 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -136,19 +136,8 @@ def debug_silent_eval(str) end end - def hbinding(hash) - code = hash.keys.map{|k| "#{k} = hash['#{k}']"}.join(';') + ';binding' - if obj = @state.context.frame_self(@state.frame_pos) - obj.instance_eval code - else - eval code - end - end - private :hbinding - def get_binding - binding = @state.context.frame_binding(@state.frame_pos) - binding || hbinding(@state.context.frame_locals(@state.frame_pos)) + @state.context.frame_binding(@state.frame_pos) end def line_at(file, line) From 36060b08b2b71261ff53ff15a4b37aa95a23a8d4 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 9 Sep 2013 16:43:32 +0400 Subject: [PATCH 012/302] fixed exec/fork monkeypathing on Kernel --- lib/ruby-debug-ide/multiprocess/monkey.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/multiprocess/monkey.rb b/lib/ruby-debug-ide/multiprocess/monkey.rb index 4c3a5ee..370f78a 100644 --- a/lib/ruby-debug-ide/multiprocess/monkey.rb +++ b/lib/ruby-debug-ide/multiprocess/monkey.rb @@ -1,9 +1,10 @@ module Debugger module MultiProcess - def self.create_mp_fork + 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{Debugger::MultiProcess::pre_child; yield} @@ -15,10 +16,11 @@ def fork(*args) } end - def self.create_mp_exec + def self.create_mp_exec(private=false) %Q{ alias pre_debugger_exec exec - + + #{private ? "private" : ""} def exec(*args) Debugger.interface.close pre_debugger_exec(*args) @@ -33,8 +35,8 @@ class << self module_eval Debugger::MultiProcess.create_mp_fork module_eval Debugger::MultiProcess.create_mp_exec end - module_eval Debugger::MultiProcess.create_mp_fork - module_eval Debugger::MultiProcess.create_mp_exec + module_eval Debugger::MultiProcess.create_mp_fork(true) + module_eval Debugger::MultiProcess.create_mp_exec(true) end module Process From e0fa3cec44e6ad16772c8a8860feb703942faf5f Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 9 Sep 2013 16:43:50 +0400 Subject: [PATCH 013/302] version bump --- lib/ruby-debug-ide/version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index d52753c..895b037 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.18' -end \ No newline at end of file + IDE_VERSION='0.4.20' +end From c61393a4e6db2df7add41357f89e8ddb34186585 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 17 Sep 2013 13:18:09 +0400 Subject: [PATCH 014/302] support viewing non-current threads backtraces --- lib/ruby-debug-ide/commands/threads.rb | 25 +++++++++++++++++++++++++ lib/ruby-debug-ide/ide_processor.rb | 11 +++++++++-- lib/ruby-debug-ide/version.rb | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/commands/threads.rb b/lib/ruby-debug-ide/commands/threads.rb index 8b9f5e7..4a63668 100644 --- a/lib/ruby-debug-ide/commands/threads.rb +++ b/lib/ruby-debug-ide/commands/threads.rb @@ -59,6 +59,31 @@ def help(cmd) end end + class ThreadInspectCommand < Command # :nodoc: + self.control = true + self.need_context = true + + def regexp + /^\s*th(?:read)?\s+in(?:spect)?\s+(\d+)\s*$/ + end + + def execute + @state.context = get_context(@match[1].to_i) + end + + class << self + def help_command + 'thread' + end + + def help(cmd) + %{ + th[read] in[spect] \tswitch thread context to nnn but don't resume any threads + } + end + end + end + class ThreadStopCommand < Command # :nodoc: self.control = true self.need_context = true diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index b9199f0..fe23f15 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -42,9 +42,10 @@ def process_commands end else @printer.print_msg "Unknown command: #{input}" - end + end end end + state.restore_context end rescue IOError, Errno::EPIPE @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @@ -105,7 +106,8 @@ def process_commands class State # :nodoc: - attr_accessor :context, :file, :line, :binding + attr_accessor :context, :original_context + attr_accessor :file, :line, :binding attr_accessor :frame_pos, :previous_line attr_accessor :interface @@ -114,6 +116,7 @@ def initialize @previous_line = nil @proceed = false yield self + @original_context = context end def print(*args) @@ -127,6 +130,10 @@ def proceed? def proceed @proceed = true end + + def restore_context + context = @original_context + end end class ControlState # :nodoc: diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index d52753c..a682d69 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.18' + IDE_VERSION='0.4.21.pre1' end \ No newline at end of file From 017c8ab405aaf6064201008132fcb36ca6c6560e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Sep 2013 12:59:16 +0400 Subject: [PATCH 015/302] improved pause command --- lib/ruby-debug-ide/commands/pause.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/commands/pause.rb b/lib/ruby-debug-ide/commands/pause.rb index b75e8b0..b485fad 100755 --- a/lib/ruby-debug-ide/commands/pause.rb +++ b/lib/ruby-debug-ide/commands/pause.rb @@ -9,12 +9,13 @@ def regexp end def execute - c = get_context(@match[1].to_i) - unless c.respond_to?(:pause) - print_msg "Not implemented" - return + Debugger.contexts.each do |c| + unless c.respond_to?(:pause) + print_msg "Not implemented" + return + end + c.pause end - c.pause end class << self From 953c3aaeacd5aa5894cf9c449198547366ebddb5 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 11 Oct 2013 18:25:58 +0400 Subject: [PATCH 016/302] Minor code cleanup to make RubyMine happy. --- bin/rdebug-ide | 2 +- lib/ruby-debug-ide.rb | 2 +- lib/ruby-debug-ide/multiprocess/pre_child.rb | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index e2ac2b6..951cc49 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -82,7 +82,7 @@ end # save script name Debugger::PROG_SCRIPT = ARGV.shift -if (options.dispatcher_port != -1) +if options.dispatcher_port != -1 ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s if RUBY_VERSION < "1.9" $: << File.expand_path(File.dirname(__FILE__) + "/../lib/") diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 6134f3c..2b9820b 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -112,7 +112,7 @@ def start_control(host, port) while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug dispatcher = ENV['IDE_PROCESS_DISPATCHER'] - if (dispatcher) + if dispatcher ENV['IDE_PROCESS_DISPATCHER'] = "#{session.peeraddr[2]}:#{dispatcher}" unless dispatcher.include?(":") ENV['DEBUGGER_HOST'] = host end diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 9cc89a4..dceb7fc 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -3,8 +3,8 @@ module MultiProcess class << self def pre_child - require "socket" - require "ostruct" + require 'socket' + require 'ostruct' host = ENV['DEBUGGER_HOST'] port = find_free_port(host) @@ -42,7 +42,7 @@ def pre_child def start_debugger(options) if Debugger.started? - #we're in forked child, only need to restart control thread + # we're in forked child, only need to restart control thread Debugger.breakpoints.clear Debugger.control_thread = nil Debugger.start_control(options.host, options.port) From acf999f385fd41f52cb578db9aeec4cc32907aa4 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 24 Oct 2013 14:28:15 +0400 Subject: [PATCH 017/302] Need to pass cli_debug flag to a child process --- bin/rdebug-ide | 1 + lib/ruby-debug-ide/multiprocess/pre_child.rb | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 951cc49..e0bfdb9 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -95,6 +95,7 @@ if options.dispatcher_port != -1 old_opts = ENV['RUBYOPT'] ENV['RUBYOPT'] = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter" ENV['RUBYOPT'] += " #{old_opts}" if old_opts + ENV['DEBUGGER_CLI_DEBUG'] = Debugger.cli_debug end if options.int_handler diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index dceb7fc..5a3caf2 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -16,7 +16,8 @@ def pre_child 'port' => port, 'stop' => false, 'tracing' => false, - 'int_handler' => true + 'int_handler' => true, + 'cli_debug' => (ENV['DEBUGGER_CLI_DEBUG'] == 'true') ) acceptor_host, acceptor_port = ENV['IDE_PROCESS_DISPATCHER'].split(":") @@ -56,6 +57,7 @@ def start_debugger(options) # set options Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing + Debugger.cli_debug = options.cli_debug Debugger.prepare_debugger(options) end From 3cf3f7079367848b18eacd89ef22dd64382a40b8 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 6 Nov 2013 16:20:38 +0300 Subject: [PATCH 018/302] debugger should report that it's listening on port when it's actually listening Otherwise we have a race between debugger and RubyMine and sometime RubyMine fails to start debugging session (http://youtrack.jetbrains.com/issue/RUBY-14490) --- lib/ruby-debug-ide.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 2b9820b..c2ad5f3 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -107,8 +107,8 @@ def start_control(host, port) host ||= '127.0.0.1' gem_name = (defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0') ? 'ruby-debug-base' : RUBY_VERSION < '2.0.0' ? 'ruby-debug-base19x' : 'debase' - $stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{gem_name} #{VERSION}) listens on #{host}:#{port}\n" server = TCPServer.new(host, port) + $stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{gem_name} #{VERSION}) listens on #{host}:#{port}\n" while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug dispatcher = ENV['IDE_PROCESS_DISPATCHER'] From d9e3793df4436c9d14e4a4d65948024c130d635a Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 12 Nov 2013 13:00:43 +0400 Subject: [PATCH 019/302] 0.4.21 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 3f592b0..970a2bd 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.21.pre1' + IDE_VERSION='0.4.21' end From 20d78a7928d8a7cd730efa0802864ec81ae7c535 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 14 Nov 2013 09:12:11 +0300 Subject: [PATCH 020/302] explicitly convert Debbuger.cli_debug to string to be able to store it in environment --- bin/rdebug-ide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index e0bfdb9..c4e3655 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -95,7 +95,7 @@ if options.dispatcher_port != -1 old_opts = ENV['RUBYOPT'] ENV['RUBYOPT'] = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter" ENV['RUBYOPT'] += " #{old_opts}" if old_opts - ENV['DEBUGGER_CLI_DEBUG'] = Debugger.cli_debug + ENV['DEBUGGER_CLI_DEBUG'] = Debugger.cli_debug.to_s end if options.int_handler From 649dccc306290f0b4c9294a73cfa29995e80fbb0 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 18 Nov 2013 12:41:24 +0400 Subject: [PATCH 021/302] 0.4.22 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 970a2bd..459f102 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.21' + IDE_VERSION='0.4.22' end From 1c0324bf877de6098d2e3d69d55a8b8f44b62c02 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 16 Dec 2013 12:19:20 +0400 Subject: [PATCH 022/302] make sure that string.bytes are referenced until thread resume --- lib/ruby-debug-ide/xml_printer.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index abc1b37..0418fd8 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -130,8 +130,12 @@ def print_hash(hash) def print_string(string) print_element("variables") do - print_variable('bytes', string.bytes.to_a, 'instance') if string.respond_to?('bytes') - print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding') + if string.respond_to?('bytes') + bytes = string.bytes.to_a + InspectCommand.reference_result(bytes) + print_variable('bytes', bytes, 'instance') + end + print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding') end end From d13955eee520fd2c5f5c4635edce2134569813b5 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 16 Dec 2013 12:24:30 +0400 Subject: [PATCH 023/302] use just binding for rbx as a temporary workaround --- lib/ruby-debug-ide/commands/variables.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index ba53b6f..0d8fa1d 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -59,6 +59,9 @@ def help(cmd) end class VarInstanceCommand < Command # :nodoc: + # TODO: try to find out a way to use Kernel.binding + BINDING_COMMAND = (defined? Rubinius) ? 'binding' : '::Kernel.binding' + def regexp # id will be read as first match, name as post match /^\s*v(?:ar)?\s+i(?:nstance)?\s+((?:[\\+-]0x)[\dabcdef]+)?/ @@ -67,8 +70,9 @@ def regexp def execute if (@match[1]) obj = ObjectSpace._id2ref(@match[1].hex) rescue nil + unless obj - # TODO: ensure that empty variables frame will be printed + print_element("variables") @printer.print_msg("Unknown object id : %s", @match[1]) end else @@ -86,7 +90,7 @@ def execute # instance variables kind = 'instance' inst_vars = obj.instance_variables - instance_binding = obj.instance_eval{::Kernel.binding()} + instance_binding = obj.instance_eval(BINDING_COMMAND) # print self at top position print_variable('self', debug_eval('self', instance_binding), kind) if inst_vars.include?('self') inst_vars.sort.each do |var| @@ -94,7 +98,7 @@ def execute end # class variables - class_binding = obj.class.class_eval('::Kernel.binding()') + class_binding = obj.class.class_eval(BINDING_COMMAND) obj.class.class_variables.sort.each do |var| print_variable(var, debug_eval(var, class_binding), 'class') end From 4f39744b9d998d97d592838851e7932d2edea753 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 31 Jan 2014 15:05:02 +0400 Subject: [PATCH 024/302] Let's notify ide dispatcher after server started to avoid race described in #38 --- lib/ruby-debug-ide.rb | 40 ++++++++++++++++---- lib/ruby-debug-ide/multiprocess/pre_child.rb | 25 ++---------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index c2ad5f3..0666679 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -2,7 +2,7 @@ require 'stringio' require "socket" require 'thread' -if (RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION)) +if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION) require 'ruby-debug-base' else require 'debase' @@ -59,14 +59,14 @@ def interrupt_last end end - def start_server(host = nil, port = 1234) + def start_server(host = nil, port = 1234, notify_dispatcher = false) return if started? start - start_control(host, port) + start_control(host, port, notify_dispatcher) end def prepare_debugger(options) - start_server(options.host, options.port) + start_server(options.host, options.port, options.notify_dispatcher) raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive? @@ -97,7 +97,7 @@ def run_prog_script end end - def start_control(host, port) + def start_control(host, port, notify_dispatcher) raise "Debugger is not started" unless started? return if @control_thread @control_thread = DebugThread.new do @@ -105,10 +105,12 @@ def start_control(host, port) # 127.0.0.1 seemingly works with all systems and with IPv6 as well. # "localhost" and nil have problems on some systems. host ||= '127.0.0.1' - gem_name = (defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0') ? 'ruby-debug-base' : - RUBY_VERSION < '2.0.0' ? 'ruby-debug-base19x' : 'debase' server = TCPServer.new(host, port) + gem_name = (defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0') ? 'ruby-debug-base' : + RUBY_VERSION < '2.0.0' ? 'ruby-debug-base19x' : 'debase' $stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{gem_name} #{VERSION}) listens on #{host}:#{port}\n" + notify_dispatcher(port) if notify_dispatcher + while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug dispatcher = ENV['IDE_PROCESS_DISPATCHER'] @@ -134,6 +136,30 @@ def start_control(host, port) end end + private + + def notify_dispatcher(port) + return unless 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 + 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 + end class Exception # :nodoc: diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 5a3caf2..1b9c2cc 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -17,28 +17,11 @@ def pre_child 'stop' => false, 'tracing' => false, 'int_handler' => true, - 'cli_debug' => (ENV['DEBUGGER_CLI_DEBUG'] == 'true') + 'cli_debug' => (ENV['DEBUGGER_CLI_DEBUG'] == 'true'), + 'notify_dispatcher' => true ) - 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 + start_debugger(options) end def start_debugger(options) @@ -46,7 +29,7 @@ def start_debugger(options) # we're in forked child, only need to restart control thread Debugger.breakpoints.clear Debugger.control_thread = nil - Debugger.start_control(options.host, options.port) + Debugger.start_control(options.host, options.port, options.notify_dispatcher) end if options.int_handler From 84f79c4a74cbac783f086036cca7c429c420cced Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 3 Feb 2014 14:47:52 +0400 Subject: [PATCH 025/302] Debug output added --- lib/ruby-debug-ide.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 0666679..02aafd2 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -150,6 +150,7 @@ def notify_dispatcher(port) s.print(port) s.close connected = true + print_debug "Ide process dispatcher notified about sub-debugger which listens on #{port}\n" return rescue => bt $stderr.puts "#{Process.pid}: connection failed(#{i+1})" From 2de04b1c78c2aca3bb63327ba22647307e431c3b Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 3 Feb 2014 14:54:52 +0400 Subject: [PATCH 026/302] Code cleanup: unused var removed and indentation fixed --- lib/ruby-debug-ide/xml_printer.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 0418fd8..f9c8343 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -282,7 +282,7 @@ def print_exception(exception, binding) InspectCommand.reference_result(proxy) print_variable('error', proxy, 'exception') end - rescue Exception => e + rescue Exception print "", exception.class, CGI.escapeHTML(exception.to_s) end @@ -294,11 +294,11 @@ def print_inspect(eval_result) end def print_load_result(file, exception=nil) - if exception then + if exception print("", file, exception.class, CGI.escapeHTML(exception.to_s)) else print("", file) - end + end end def print_element(name) From 95df2d29740eb4420a1aea53923675e18fde8e42 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 3 Feb 2014 15:14:36 +0400 Subject: [PATCH 027/302] Both ruby and RubyMine think that "context" is a local variable but not a setter for @context :( --- lib/ruby-debug-ide/ide_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index fe23f15..7cf190f 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -132,7 +132,7 @@ def proceed end def restore_context - context = @original_context + @context = @original_context end end From 1335a15f16a1cece0d55757e1ea3c79f5e0aae5b Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 3 Feb 2014 15:19:59 +0400 Subject: [PATCH 028/302] Code cleanup: indentation fixed --- lib/ruby-debug-ide/commands/jump.rb | 2 +- lib/ruby-debug-ide/commands/pause.rb | 2 +- lib/ruby-debug-ide/commands/set_type.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/commands/jump.rb b/lib/ruby-debug-ide/commands/jump.rb index 7c7c1c8..82eb7dc 100755 --- a/lib/ruby-debug-ide/commands/jump.rb +++ b/lib/ruby-debug-ide/commands/jump.rb @@ -67,7 +67,7 @@ def help(cmd) Change the next line of code to be executed. } - end + end end end end diff --git a/lib/ruby-debug-ide/commands/pause.rb b/lib/ruby-debug-ide/commands/pause.rb index b485fad..b44aa48 100755 --- a/lib/ruby-debug-ide/commands/pause.rb +++ b/lib/ruby-debug-ide/commands/pause.rb @@ -27,7 +27,7 @@ def help(cmd) %{ pause \tpause a running thread } - end + end end end end diff --git a/lib/ruby-debug-ide/commands/set_type.rb b/lib/ruby-debug-ide/commands/set_type.rb index 10ff8c8..aebbee7 100755 --- a/lib/ruby-debug-ide/commands/set_type.rb +++ b/lib/ruby-debug-ide/commands/set_type.rb @@ -41,7 +41,7 @@ def help(cmd) Change the type of to } - end + end end end end From e216560856f740fc19b60868260e60d028466344 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 3 Feb 2014 15:20:23 +0400 Subject: [PATCH 029/302] Code cleanup: ruby warnings fixed --- lib/ruby-debug-ide/commands/condition.rb | 4 ++-- lib/ruby-debug-ide/commands/enable.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/commands/condition.rb b/lib/ruby-debug-ide/commands/condition.rb index 0774ac7..f0bcaa7 100644 --- a/lib/ruby-debug-ide/commands/condition.rb +++ b/lib/ruby-debug-ide/commands/condition.rb @@ -12,8 +12,8 @@ def execute errmsg "\"condition\" must be followed a breakpoint number and expression\n" else breakpoints = Debugger.breakpoints.sort_by{|b| b.id } - largest = breakpoints.inject(0) do |largest, b| - largest = b.id if b.id > largest + largest = breakpoints.inject(0) do |largest_so_far, b| + b.id if b.id > largest_so_far end if 0 == largest print "No breakpoints have been set.\n" diff --git a/lib/ruby-debug-ide/commands/enable.rb b/lib/ruby-debug-ide/commands/enable.rb index 51b7221..99c6ecb 100644 --- a/lib/ruby-debug-ide/commands/enable.rb +++ b/lib/ruby-debug-ide/commands/enable.rb @@ -3,8 +3,8 @@ module Debugger module EnableDisableFunctions # :nodoc: def enable_disable_breakpoints(is_enable, args) breakpoints = Debugger.breakpoints.sort_by{|b| b.id } - largest = breakpoints.inject(0) do |largest, b| - largest = b.id if b.id > largest + largest = breakpoints.inject(0) do |largest_so_far, b| + b.id if b.id > largest_so_far end if 0 == largest errmsg "No breakpoints have been set.\n" From 83d75a9cc2caf30934ded201408220b8fe713460 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 12 Feb 2014 13:20:45 +0400 Subject: [PATCH 030/302] More debug output --- lib/ruby-debug-ide/ide_processor.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index fe23f15..7857105 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -94,9 +94,11 @@ def process_commands end end rescue IOError, Errno::EPIPE + @printer.print_debug "INTERNAL ERROR!!! #{$!}\n" @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil rescue Exception + @printer.print_debug "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil ensure From 21e6da445f34e79afd99f5390966a9d285fdd4c3 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 12 Feb 2014 16:25:07 +0400 Subject: [PATCH 031/302] More debug output --- lib/ruby-debug-ide/interface.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/interface.rb b/lib/ruby-debug-ide/interface.rb index 90cf78a..093b9e7 100644 --- a/lib/ruby-debug-ide/interface.rb +++ b/lib/ruby-debug-ide/interface.rb @@ -23,10 +23,17 @@ class LocalInterface < Interface class RemoteInterface < Interface # :nodoc: attr_accessor :command_queue - attr_accessor :socket + #attr_accessor :socket def initialize(socket) @socket = socket + class <<@socket + alias close_without_logging close + def close + close_without_logging + $stderr.puts "medvedko is " + ::Kernel.caller(1).join("\n") + end + end @command_queue = Queue.new end From c532e432478fcaf002a0a6def6327fa441922bed Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 11:16:41 +0400 Subject: [PATCH 032/302] Let's rescue IOError instead of Exception. Debug output removed --- lib/ruby-debug-ide/interface.rb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/ruby-debug-ide/interface.rb b/lib/ruby-debug-ide/interface.rb index 093b9e7..018d2d5 100644 --- a/lib/ruby-debug-ide/interface.rb +++ b/lib/ruby-debug-ide/interface.rb @@ -23,17 +23,9 @@ class LocalInterface < Interface class RemoteInterface < Interface # :nodoc: attr_accessor :command_queue - #attr_accessor :socket def initialize(socket) @socket = socket - class <<@socket - alias close_without_logging close - def close - close_without_logging - $stderr.puts "medvedko is " + ::Kernel.caller(1).join("\n") - end - end @command_queue = Queue.new end @@ -49,7 +41,7 @@ def print(*args) def close @socket.close - rescue Exception + rescue IOError end end From 7c7d5865c0d8a69707fc7ab337c264cce8c506e4 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 11:21:36 +0400 Subject: [PATCH 033/302] Need to initialize @mutex and @proceed before calling start_server() to avoid possible thread-race --- lib/ruby-debug-ide.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 02aafd2..27de4de 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -66,13 +66,13 @@ def start_server(host = nil, port = 1234, notify_dispatcher = false) end def prepare_debugger(options) + @mutex = Mutex.new + @proceed = ConditionVariable.new + start_server(options.host, options.port, options.notify_dispatcher) raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive? - @mutex = Mutex.new - @proceed = ConditionVariable.new - # wait for 'start' command @mutex.synchronize do @proceed.wait(@mutex) From 6d7a50ee8bc876f85aa1404fcaccd0e8f129df19 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 16:02:59 +0400 Subject: [PATCH 034/302] Let's log exception's class --- lib/ruby-debug-ide.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 27de4de..782118b 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -124,7 +124,7 @@ def start_control(host, port, notify_dispatcher) IdeControlCommandProcessor.new(interface).process_commands rescue StandardError, ScriptError => ex bt = ex.backtrace - $stderr.printf "#{Process.pid}: Exception in DebugThread loop: #{ex.message}\nBacktrace:\n#{bt ? bt.join("\n from: ") : ""}\n" + $stderr.printf "#{Process.pid}: Exception in DebugThread loop: #{ex.message}(#{ex.class})\nBacktrace:\n#{bt ? bt.join("\n from: ") : ""}\n" exit 1 end end From 2767296e8b8b737cef4decba4fb175a37185e426 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 16:03:59 +0400 Subject: [PATCH 035/302] It looks like sometimes closed socket may cause ENOTSOCK exception --- lib/ruby-debug-ide/ide_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index 7857105..875675b 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -93,7 +93,7 @@ def process_commands end end end - rescue IOError, Errno::EPIPE + rescue IOError, Errno::EPIPE, Errno::ENOTSOCK @printer.print_debug "INTERNAL ERROR!!! #{$!}\n" @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil From 7ac8b4e068460f35b664beaef5fb64564e2dba64 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 20:31:23 +0400 Subject: [PATCH 036/302] Need to catch SystemCallError to catch all Errno::XXX --- lib/ruby-debug-ide/ide_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index 875675b..b23af1b 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -93,7 +93,7 @@ def process_commands end end end - rescue IOError, Errno::EPIPE, Errno::ENOTSOCK + rescue IOError, SystemCallError @printer.print_debug "INTERNAL ERROR!!! #{$!}\n" @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil From 0eefd181fa4a5d93a35320db7feacba6b0da4e40 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 20:40:00 +0400 Subject: [PATCH 037/302] One more place where we should catch SystemCallError --- lib/ruby-debug-ide/ide_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index b23af1b..231046d 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -47,7 +47,7 @@ def process_commands end state.restore_context end - rescue IOError, Errno::EPIPE + rescue IOError, SystemCallError @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil rescue Exception From 2064c9af41c523ff2d6743e25f1939a510697dd6 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Feb 2014 20:40:47 +0400 Subject: [PATCH 038/302] We do not need this monkey-patching --- lib/ruby-debug-ide/interface.rb | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/ruby-debug-ide/interface.rb b/lib/ruby-debug-ide/interface.rb index 018d2d5..f98d210 100644 --- a/lib/ruby-debug-ide/interface.rb +++ b/lib/ruby-debug-ide/interface.rb @@ -1,19 +1,6 @@ require 'thread' -class TCPSocket - - # Workaround for JRuby issue http://jira.codehaus.org/browse/JRUBY-2063 - def non_blocking_gets - loop do - result, _, _ = IO.select( [self], nil, nil, 0.2 ) - next unless result - return result[0].gets - end - end - -end - -module Debugger +module Debugger class Interface end @@ -30,7 +17,7 @@ def initialize(socket) end def read_command - result = @socket.non_blocking_gets + result = non_blocking_gets raise IOError unless result result.chomp end @@ -43,7 +30,16 @@ def close @socket.close rescue IOError end - + + # Workaround for JRuby issue http://jira.codehaus.org/browse/JRUBY-2063 + def non_blocking_gets + loop do + result, _, _ = IO.select( [@socket], nil, nil, 0.2 ) + next unless result + return result[0].gets + end + end + end end From eb9dfd6e5fb15e7073313fb890b6f7abf424d0a7 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Sun, 23 Mar 2014 15:42:14 +0400 Subject: [PATCH 039/302] do not install dependencies for rubinius --- ext/mkrf_conf.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/mkrf_conf.rb b/ext/mkrf_conf.rb index 14a9989..08c94d0 100644 --- a/ext/mkrf_conf.rb +++ b/ext/mkrf_conf.rb @@ -1,11 +1,12 @@ jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE) +rbx = defined?(RUBY_ENGINE) && 'rbx' == RUBY_ENGINE def already_installed(dep) !Gem::DependencyInstaller.new(:domain => :local).find_gems_with_sources(dep).empty? || !Gem::DependencyInstaller.new(:domain => :local,:prerelease => true).find_gems_with_sources(dep).empty? end -unless jruby +unless jruby || rbx require 'rubygems' require 'rubygems/command.rb' require 'rubygems/dependency.rb' From 1d4b1dd6024e18ef8dab76e2473b63a69ea99580 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Sun, 23 Mar 2014 15:43:34 +0400 Subject: [PATCH 040/302] version bump --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 459f102..c7a17c8 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.22' + IDE_VERSION='0.4.23.beta1' end From 38b748e0313756e2b46495c11e918d9a2ed8a9fe Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 13 May 2014 16:56:50 +0400 Subject: [PATCH 041/302] Test fixed: String has children --- test-base/variables_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 46cac98..14efeb7 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -79,7 +79,7 @@ def test_variable_string # Read numerical variable send_ruby("frame 1; v l") assert_variables(read_variables, 1, - {:name => "stringA", :value => "XX", :type => "String", :hasChildren => false}) + {:name => "stringA", :value => "XX", :type => "String", :hasChildren => true}) send_cont end From b82e025a1106980f5bd9ec383befca2ff1fde6d4 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 13 May 2014 17:01:33 +0400 Subject: [PATCH 042/302] Passing string value of a variable as text of sub-element To be able to pass \n and other characters which can not be passed inside attribute. See http://youtrack.jetbrains.com/issue/RUBY-13641 for details. --- lib/ruby-debug-ide/xml_printer.rb | 4 +++- test-base/readers.rb | 21 ++++++++++++++++++--- test-base/variables_test.rb | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index f9c8343..346ea0f 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -170,9 +170,11 @@ def print_variable(name, value, kind) end end value_str = "[Binary Data]" if (value_str.respond_to?('is_binary_data?') && value_str.is_binary_data?) - print("", + print("", CGI.escapeHTML(name), kind, CGI.escapeHTML(value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) + print("", value_str) + print('') end def print_breakpoints(breakpoints) diff --git a/test-base/readers.rb b/test-base/readers.rb index 9aa4ce2..d2f4405 100644 --- a/test-base/readers.rb +++ b/test-base/readers.rb @@ -114,7 +114,7 @@ def read_start_element(expected_element) def read_text event = @parser.pull - fail("expected \":text\" event, but got \"#{event.inspect}\"") unless event.text? + fail("expected \":text\" event, but got \"#{event.inspect}\"") unless event.text? || event.cdata? event[0] end @@ -234,10 +234,25 @@ def read case event.event_type when :start_element check_event(:start_element, 'variable', event) - ensure_end_element('variable') + value_event = @parser.pull + if value_event.event_type == :start_element + check_event(:start_element, 'value', value_event) + text_value = read_text + ensure_end_element('value') + ensure_end_element('variable') + else + text_value = event[1]['value'] + check_event(:end_element, 'variable', value_event) + end variables << Variable.new(*Variable.members.map { |m| value = event[1][m.to_s] - m.to_s == 'hasChildren' ? value == "true" : value + if m.to_s == 'hasChildren' + value == 'true' + elsif m.to_s == 'value' + text_value + else + value + end }) when :end_element check_event(:end_element, 'variables', event) diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 14efeb7..e0d3140 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -25,7 +25,7 @@ def test_variable_with_xml_content {:name => "stringA"}, {:name => "testHashValue"}) # will receive '' - assert_xml("", variables[0].value) + assert_equal("", variables[0].value) assert_local(variables[0]) # the testHashValue contains an example, where the name consists of special # characters From 40b4652ac34257750ad102cc81964117b17c129e Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 1 Jul 2014 12:53:41 +0400 Subject: [PATCH 043/302] adding 'more' command; raising version to beta2 --- lib/ruby-debug-ide/commands/inspect.rb | 36 +++++++++++++++++++++++++- lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/inspect.rb b/lib/ruby-debug-ide/commands/inspect.rb index dfe04ce..beef7f3 100644 --- a/lib/ruby-debug-ide/commands/inspect.rb +++ b/lib/ruby-debug-ide/commands/inspect.rb @@ -22,4 +22,38 @@ def execute end end -end \ No newline at end of file + class MoreCommand < Command + def regexp + /^\s*more\s+/ + end + + def execute + require 'stringio' + require 'irb/ruby-lex' + + string_to_parse = @match.post_match.gsub("\\n", "\n") + "\n\n\n" + + lexer = RubyLex.new + io = StringIO.new(string_to_parse) + # for passing to the lexer + def io.encoding + "utf-8" + end + lexer.set_input(io) + lexer.set_prompt {|ltype, indent, continue, lineno| } + + last_statement = '',0 + lexer.each_top_level_statement do |line, line_no| + last_statement = line, line_no + end + + result = 1 + if /\A\s*\Z/m =~ last_statement[0] + result = 0 + end + + @printer.print_pp("") + end + end + +end diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index c7a17c8..2c22bbd 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta1' + IDE_VERSION='0.4.23.beta2' end From ac48c48ebdbf4183f74237071c2621f82abfb0b9 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 1 Jul 2014 16:11:23 +0400 Subject: [PATCH 044/302] rename and move 'more' command to expression_info; set string encoding for stringIO --- .../commands/expression_info.rb | 56 +++++++++++++++++++ lib/ruby-debug-ide/commands/inspect.rb | 34 ----------- 2 files changed, 56 insertions(+), 34 deletions(-) create mode 100644 lib/ruby-debug-ide/commands/expression_info.rb diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb new file mode 100644 index 0000000..484709a --- /dev/null +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -0,0 +1,56 @@ +require 'stringio' +require 'irb/ruby-lex' + +module Debugger + + class ExpressionInfoCommand < Command + def regexp + /^\s*ex(?:pression_info)?\s+/ + end + + def execute + string_to_parse = @match.post_match.gsub("\\n", "\n") + "\n\n\n" + + lexer = RubyLex.new + io = StringIO.new(string_to_parse) + # for passing to the lexer + io.instance_exec(string_to_parse.encoding) do |string_encoding| + @my_encoding = string_encoding + def self.encoding + @my_encoding + end + end + + lexer.set_input(io) + lexer.set_prompt {|ltype, indent, continue, lineno| } + + last_statement = '',0 + lexer.each_top_level_statement do |line, line_no| + last_statement = line, line_no + end + + result = true + if /\A\s*\Z/m =~ last_statement[0] + result = false + end + + @printer.print_pp("") + end + + class << self + def help_command + "expression_info" + end + + def help(cmd) + %{ + ex[pression_info] \t + returns parser-related information for the expression given\t\t + 'incomplete'=true|false\tindicates whether expression is a complete ruby + expression and can be evaluated without getting syntax errors + } + end + end + end + +end diff --git a/lib/ruby-debug-ide/commands/inspect.rb b/lib/ruby-debug-ide/commands/inspect.rb index beef7f3..3d4513c 100644 --- a/lib/ruby-debug-ide/commands/inspect.rb +++ b/lib/ruby-debug-ide/commands/inspect.rb @@ -22,38 +22,4 @@ def execute end end - class MoreCommand < Command - def regexp - /^\s*more\s+/ - end - - def execute - require 'stringio' - require 'irb/ruby-lex' - - string_to_parse = @match.post_match.gsub("\\n", "\n") + "\n\n\n" - - lexer = RubyLex.new - io = StringIO.new(string_to_parse) - # for passing to the lexer - def io.encoding - "utf-8" - end - lexer.set_input(io) - lexer.set_prompt {|ltype, indent, continue, lineno| } - - last_statement = '',0 - lexer.each_top_level_statement do |line, line_no| - last_statement = line, line_no - end - - result = 1 - if /\A\s*\Z/m =~ last_statement[0] - result = 0 - end - - @printer.print_pp("") - end - end - end From 1d19a95f7e1b644eecb4006d2c20dccc7036173a Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 2 Jul 2014 14:15:26 +0400 Subject: [PATCH 045/302] storage of unused values fixed --- lib/ruby-debug-ide/commands/expression_info.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index 484709a..c709d60 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -24,17 +24,17 @@ def self.encoding lexer.set_input(io) lexer.set_prompt {|ltype, indent, continue, lineno| } - last_statement = '',0 + last_statement = '' lexer.each_top_level_statement do |line, line_no| - last_statement = line, line_no + last_statement = line end - result = true + incomplete = true if /\A\s*\Z/m =~ last_statement[0] - result = false + incomplete = false end - @printer.print_pp("") + @printer.print_pp("") end class << self From b204643b0b412cc69b78cafce2a59ea05f493af9 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 2 Jul 2014 14:38:50 +0400 Subject: [PATCH 046/302] added indent and prompt type output for expression_info --- .../commands/expression_info.rb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index c709d60..dad4b02 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -10,6 +10,7 @@ def regexp def execute string_to_parse = @match.post_match.gsub("\\n", "\n") + "\n\n\n" + total_lines = string_to_parse.count("\n") + 1 lexer = RubyLex.new io = StringIO.new(string_to_parse) @@ -22,9 +23,17 @@ def self.encoding end lexer.set_input(io) - lexer.set_prompt {|ltype, indent, continue, lineno| } last_statement = '' + last_prompt = '' + last_indent = 0 + lexer.set_prompt do |ltype, indent, continue, lineno| + next if (lineno >= total_lines) + + last_prompt = ltype || '' + last_indent = indent + end + lexer.each_top_level_statement do |line, line_no| last_statement = line end @@ -34,7 +43,13 @@ def self.encoding incomplete = false end - @printer.print_pp("") + @printer.print_pp <<-EOF.gsub(/\n */, ' ').gsub(/>\s+<').strip + + + EOF end class << self From e2d685fe644eda6327ab0d92f27a79db97ff8e26 Mon Sep 17 00:00:00 2001 From: Adam Russell Date: Mon, 14 Jul 2014 11:22:01 -0400 Subject: [PATCH 047/302] Add IntelliJ IDEA Ruby plugin to usage text. --- bin/rdebug-ide | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index c4e3655..bad8d24 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -24,8 +24,9 @@ options = OpenStruct.new( opts = OptionParser.new do |opts| opts.banner = < Date: Wed, 16 Jul 2014 13:38:40 +0400 Subject: [PATCH 048/302] move xml printing details to xml_printer --- lib/ruby-debug-ide/commands/expression_info.rb | 8 +------- lib/ruby-debug-ide/xml_printer.rb | 5 +++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index dad4b02..d2ca641 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -43,13 +43,7 @@ def self.encoding incomplete = false end - @printer.print_pp <<-EOF.gsub(/\n */, ' ').gsub(/>\s+<').strip - - - EOF + @printer.print_expression_info(incomplete, last_prompt, last_indent) end class << self diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 346ea0f..5181b68 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -220,6 +220,11 @@ def print_expressions(exps) def print_expression(exp, value, idx) print "", exp, value, idx end + + def print_expression_info(incomplete, prompt, indent) + print "", + incomplete, CGI.escapeHTML(prompt), indent + end def print_eval(exp, value) print "", CGI.escapeHTML(exp), value From ffff13c83e3a8b0e95b491abe1a4f6b31c01617e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 16 Jul 2014 17:32:25 +0400 Subject: [PATCH 049/302] Evaluation timeout has been made configurable --- bin/rdebug-ide | 9 +++++++-- lib/ruby-debug-ide.rb | 2 +- lib/ruby-debug-ide/command.rb | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index bad8d24..888ce5c 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -18,7 +18,8 @@ options = OpenStruct.new( 'stop' => false, 'tracing' => false, 'int_handler' => true, - 'dispatcher_port' => -1 + 'dispatcher_port' => -1, + 'evaluation_timeout' => 10 ) opts = OptionParser.new do |opts| @@ -34,7 +35,10 @@ EOB opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| options.dispatcher_port = dp - end + end + opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout| + options.evaluation_timeout = timeout + end opts.on('--stop', 'stop when the script is loaded') {options.stop = true} opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true} opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true} @@ -107,6 +111,7 @@ end # set options Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing +Debugger.evaluation_timeout = options.evaluation_timeout Debugger.debug_program(options) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 782118b..3853852 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -41,7 +41,7 @@ def cleanup_backtrace(backtrace) cleared end - attr_accessor :cli_debug, :xml_debug + attr_accessor :cli_debug, :xml_debug, :evaluation_timeout attr_accessor :control_thread attr_reader :interface diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 2c76632..702fd88 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -115,7 +115,7 @@ def timeout(sec) def debug_eval(str, b = get_binding) begin str = str.to_s - max_time = 10 + max_time = Debugger.evaluation_timeout to_inspect = str.gsub(/\\n/, "\n") @printer.print_debug("Evaluating #{str} with timeout after %i sec", max_time) timeout(max_time) do From f2402f06dad30693b29e523cb3d7d95db23bf741 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 13 Aug 2014 19:21:58 +0400 Subject: [PATCH 050/302] Need to use realpath for breakpoints to be compatible with ruby-debug and debase --- lib/ruby-debug-ide/commands/breakpoints.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index 6d65d78..18ce44c 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -1,3 +1,5 @@ +require 'pathname' if RUBY_VERSION < '1.9' + module Debugger class AddBreakpoint < Command # :nodoc: self.control = true @@ -35,8 +37,7 @@ def execute end file = klass.name if klass else - file = File.expand_path(file) if file.index(File::SEPARATOR) || \ - File::ALT_SEPARATOR && file.index(File::ALT_SEPARATOR) + file = realpath(file) end end @@ -63,6 +64,19 @@ def help(cmd) } end end + + private + def realpath(filename) + filename = File.expand_path(file) if file.index(File::SEPARATOR) || \ + File::ALT_SEPARATOR && file.index(File::ALT_SEPARATOR) + if defined?(JRUBY_VERSION) + java.io.File.new(filename).canonical_path + elsif RUBY_VERSION < '1.9' + File.path(Pathname.new(filename).realpath) + else + File.realpath(filename) + end + end end class BreakpointsCommand < Command # :nodoc: From 5864d7045d522787a38b241882ab642152340f94 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 13 Aug 2014 19:22:47 +0400 Subject: [PATCH 051/302] version bumped up --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 2c22bbd..b50a021 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta2' + IDE_VERSION='0.4.23.beta3' end From eabac80955af6acbdd66cddc236db8b0d4592a07 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 13 Aug 2014 19:30:00 +0400 Subject: [PATCH 052/302] variable's name corrected --- lib/ruby-debug-ide/commands/breakpoints.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index 18ce44c..6bea6c2 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -67,8 +67,8 @@ def help(cmd) private def realpath(filename) - filename = File.expand_path(file) if file.index(File::SEPARATOR) || \ - File::ALT_SEPARATOR && file.index(File::ALT_SEPARATOR) + filename = File.expand_path(filename) if filename.index(File::SEPARATOR) || \ + File::ALT_SEPARATOR && filename.index(File::ALT_SEPARATOR) if defined?(JRUBY_VERSION) java.io.File.new(filename).canonical_path elsif RUBY_VERSION < '1.9' From 81039a0c51d96b640c845e268972400a611e6c0d Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 13 Aug 2014 19:41:49 +0400 Subject: [PATCH 053/302] fixed realpath for 1.8 --- lib/ruby-debug-ide/commands/breakpoints.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index 6bea6c2..63a0cff 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -72,7 +72,7 @@ def realpath(filename) if defined?(JRUBY_VERSION) java.io.File.new(filename).canonical_path elsif RUBY_VERSION < '1.9' - File.path(Pathname.new(filename).realpath) + Pathname.new(filename).realpath.to_s else File.realpath(filename) end From cc01029f1699c3fd91b5780e5db6c98525199ab2 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 13 Aug 2014 20:06:26 +0400 Subject: [PATCH 054/302] we do not need realpath for 1.8 --- lib/ruby-debug-ide/commands/breakpoints.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index 63a0cff..0c42f95 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -72,7 +72,7 @@ def realpath(filename) if defined?(JRUBY_VERSION) java.io.File.new(filename).canonical_path elsif RUBY_VERSION < '1.9' - Pathname.new(filename).realpath.to_s + filename else File.realpath(filename) end From 7ff15605eca0f111580ec79e8934042c634059c0 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 13 Aug 2014 20:07:08 +0400 Subject: [PATCH 055/302] need to catch SystemCallError in Interface.error --- lib/ruby-debug-ide/interface.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/interface.rb b/lib/ruby-debug-ide/interface.rb index f98d210..3d68ba0 100644 --- a/lib/ruby-debug-ide/interface.rb +++ b/lib/ruby-debug-ide/interface.rb @@ -28,7 +28,7 @@ def print(*args) def close @socket.close - rescue IOError + rescue IOError, SystemCallError end # Workaround for JRuby issue http://jira.codehaus.org/browse/JRUBY-2063 From 5a2227c3669e6097e5a29bdf66a417ffb0b558fb Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 22 Aug 2014 11:26:53 +0400 Subject: [PATCH 056/302] Need to escape xml tags even in CDATA to avoid problems with strings like "]]<\something>" --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 5181b68..a3d33f9 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -173,7 +173,7 @@ def print_variable(name, value, kind) print("", CGI.escapeHTML(name), kind, CGI.escapeHTML(value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) - print("", value_str) + print("", CGI.escapeHTML(value_str)) print('') end From d8af0cc1fe27788f5e8dd36772043576f299fe6c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 22 Aug 2014 11:27:07 +0400 Subject: [PATCH 057/302] Version bumped up --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index b50a021..aad64bc 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta3' + IDE_VERSION='0.4.23.beta4' end From 5b6f03f7e4b08f3eb579bbd08073a947daeca7f8 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 22 Aug 2014 21:40:57 +0400 Subject: [PATCH 058/302] Let's use SimpleDelegator to delegates calls to Printer --- lib/ruby-debug-ide/command.rb | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 702fd88..ff09273 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -1,8 +1,9 @@ require 'ruby-debug-ide/helper' +require 'delegate' module Debugger - class Command # :nodoc: + class Command < SimpleDelegator # :nodoc: SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless defined?(SubcmdStruct) @@ -67,6 +68,7 @@ def options def initialize(state, printer) @state, @printer = state, printer + super @printer end def match(input) @@ -75,15 +77,6 @@ def match(input) protected - def method_missing(meth, *args, &block) - if @printer.respond_to? meth - @printer.send meth, *args, &block - else - super - end - end - - # FIXME: use delegate? def errmsg(*args) @printer.print_error(*args) end From 71a05cbaa3eafb79140b0f0aa0d9107f93348699 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 22 Aug 2014 21:41:08 +0400 Subject: [PATCH 059/302] Version bumped up --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index aad64bc..120dcb8 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta4' + IDE_VERSION='0.4.23.beta5' end From 17f83297fe89cfd1ea24016b6da665987a4004fc Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 25 Aug 2014 13:00:13 +0400 Subject: [PATCH 060/302] support for inline debugger rendering --- lib/ruby-debug-ide/xml_printer.rb | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index a3d33f9..265f9fe 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -170,12 +170,30 @@ def print_variable(name, value, kind) end end value_str = "[Binary Data]" if (value_str.respond_to?('is_binary_data?') && value_str.is_binary_data?) - print("", - CGI.escapeHTML(name), kind, CGI.escapeHTML(value_str), value.class, + compact_value_str = build_compact_name(value_str, value) + print("", + CGI.escapeHTML(name), CGI.escapeHTML(compact_value_str), kind, CGI.escapeHTML(value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) print("", CGI.escapeHTML(value_str)) print('') end + + def build_compact_name(value_str, value) + compact = value_str + if value.is_a?(Array) + slice = value[0..10] + compact = slice.inspect + if (value.size != slice.size) + compact = compact[0..compact.size-2] + ", ...]" + end + end + if value.is_a?(Hash) + slice = value.sort_by { |k,v| k }[0..5] + compact = slice.map {|kv| "#{kv[0]}: #{kv[1]}"}.join(", ") + compact = "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" + end + compact + end def print_breakpoints(breakpoints) print_element 'breakpoints' do From 5aa131b0661ca196c3619e595606217393910153 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 25 Aug 2014 13:03:39 +0400 Subject: [PATCH 061/302] c'mon it's 2014 already --- lib/ruby-debug-ide/xml_printer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 265f9fe..d7cbb10 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -150,7 +150,8 @@ def print_variable(name, value, kind) unless has_children value_str = "Empty #{value.class}" else - value_str = "#{value.class} (#{value.size} element(s))" + size = value.size + value_str = "#{value.class} (#{value.size} element#{size > 1 ? "s" : "" })" end elsif value.is_a?(String) has_children = value.respond_to?('bytes') || value.respond_to?('encoding') From a7745d14eeb365116785ca7a073133b9d62a6773 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 25 Aug 2014 13:04:10 +0400 Subject: [PATCH 062/302] version bump --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 120dcb8..bbc9a34 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta5' + IDE_VERSION='0.4.23.beta6' end From a71aad63036126109ce5121b437c4e26a86976c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Jacques?= Date: Wed, 27 Aug 2014 10:58:19 -0400 Subject: [PATCH 063/302] For ruby 1.9.3, prefer a version of ruby-debug-base19x that doesn't depend on linecache19 nor columnize gems --- ext/mkrf_conf.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/mkrf_conf.rb b/ext/mkrf_conf.rb index 08c94d0..e1a40af 100644 --- a/ext/mkrf_conf.rb +++ b/ext/mkrf_conf.rb @@ -19,6 +19,8 @@ def already_installed(dep) if RUBY_VERSION < "1.9" dep = Gem::Dependency.new("ruby-debug-base", '>=0.10.4') + elsif RUBY_VERSION >= '1.9.3' + dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.30.pre15') elsif RUBY_VERSION < '2.0' dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.24') else @@ -27,11 +29,11 @@ def already_installed(dep) begin puts "Installing base gem" - inst = Gem::DependencyInstaller.new + inst = Gem::DependencyInstaller.new :prerelease => dep.prerelease? inst.install dep rescue - inst = Gem::DependencyInstaller.new(:prerelease => true) begin + inst = Gem::DependencyInstaller.new(:prerelease => true) inst.install dep rescue Exception => e puts e From ae7b0bde798808678ed3ccf32370538daa7a08c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Jacques?= Date: Fri, 29 Aug 2014 15:53:16 -0400 Subject: [PATCH 064/302] Use same version for all versions of ruby 1.9.x --- ext/mkrf_conf.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/mkrf_conf.rb b/ext/mkrf_conf.rb index e1a40af..c8170ac 100644 --- a/ext/mkrf_conf.rb +++ b/ext/mkrf_conf.rb @@ -19,10 +19,8 @@ def already_installed(dep) if RUBY_VERSION < "1.9" dep = Gem::Dependency.new("ruby-debug-base", '>=0.10.4') - elsif RUBY_VERSION >= '1.9.3' - dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.30.pre15') elsif RUBY_VERSION < '2.0' - dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.24') + dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.30.pre15') else dep = Gem::Dependency.new("debase", '> 0') end From 9560dbb52a5a3376a6e07ff1378301d6c6625502 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 3 Sep 2014 12:39:14 +0400 Subject: [PATCH 065/302] Version bumped up to 0.4.23.beta7 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index bbc9a34..5cd6019 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta6' + IDE_VERSION='0.4.23.beta7' end From 6f3c19343b66089e91d8349d18f77609bcbfef9c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 3 Sep 2014 12:46:21 +0400 Subject: [PATCH 066/302] let's ignore .ruby-version, .ruby-gemset, .ide --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 4040c6c..81a1c37 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ .bundle Gemfile.lock pkg/* +.ruby-version +.ruby-gemset +.idea \ No newline at end of file From 7117f57eb616b4bd84121862eb95f73676bd7efa Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Sep 2014 15:05:13 +0400 Subject: [PATCH 067/302] version bumped to 0.4.23.beta8 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 5cd6019..613be3c 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta7' + IDE_VERSION='0.4.23.beta8' end From 0990c7a9edbbd74373be9e8fab7285bf828a460c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Sep 2014 15:10:29 +0400 Subject: [PATCH 068/302] Fixing realpath conversion for JRuby on Windows On Windows we should not convert path to realpath for JRuby because canonical path will contain \ while Ruby always uses / and after this conversion we do not stop on breakpoints :( Also JRUBY_VERSION may not be initialised at this point (at least for initial breakpoint it is not :( --- lib/ruby-debug-ide/commands/breakpoints.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index 0c42f95..5644f21 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -1,5 +1,3 @@ -require 'pathname' if RUBY_VERSION < '1.9' - module Debugger class AddBreakpoint < Command # :nodoc: self.control = true @@ -69,9 +67,7 @@ def help(cmd) def realpath(filename) filename = File.expand_path(filename) if filename.index(File::SEPARATOR) || \ File::ALT_SEPARATOR && filename.index(File::ALT_SEPARATOR) - if defined?(JRUBY_VERSION) - java.io.File.new(filename).canonical_path - elsif RUBY_VERSION < '1.9' + if (RUBY_VERSION < '1.9') || (RbConfig::CONFIG['host_os'] =~ /mswin/) filename else File.realpath(filename) From 3cf798d3ab8f0d6f280eecd5bba09cb2e8dd9b58 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 22 Sep 2014 23:50:30 +0400 Subject: [PATCH 069/302] ::Kernel.binding doesn't work for ruby 1.8 should use binding instead --- lib/ruby-debug-ide/commands/variables.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index 0d8fa1d..3414fcf 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -59,8 +59,9 @@ def help(cmd) end class VarInstanceCommand < Command # :nodoc: - # TODO: try to find out a way to use Kernel.binding - BINDING_COMMAND = (defined? Rubinius) ? 'binding' : '::Kernel.binding' + # TODO: try to find out a way to use Kernel.binding for Rubinius + # ::Kernel.binding doesn't for for ruby 1.8 (see RUBY-14679) + BINDING_COMMAND = (defined?(Rubinius) || RUBY_VERSION < '1.9') ? 'binding' : '::Kernel.binding' def regexp # id will be read as first match, name as post match From 6aef7b7c2b765ca2a6eb9f88fcf4009afe4fceaf Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 23 Sep 2014 00:00:19 +0400 Subject: [PATCH 070/302] version bumped up --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 613be3c..00cd78f 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta8' + IDE_VERSION='0.4.23.beta9' end From 88082103d97d9d1a88fa7b32c26f9f2e1bb04403 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 25 Sep 2014 13:05:10 +0400 Subject: [PATCH 071/302] Update and rename ChangeLog to ChangeLog.md --- ChangeLog => ChangeLog.md | 3 +++ 1 file changed, 3 insertions(+) rename ChangeLog => ChangeLog.md (99%) diff --git a/ChangeLog b/ChangeLog.md similarity index 99% rename from ChangeLog rename to ChangeLog.md index 97b8fc5..0e4a982 100644 --- a/ChangeLog +++ b/ChangeLog.md @@ -1,3 +1,6 @@ +## [0.4.23.beta9](https://ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...v0.4.23.beta9) + +## "per-historical" changes Dennis Ushakov * run context commands on stopped thread to prevent segfaults (3c1b52d5091fccec447d5695d5b43e73f335cc54) * enable building without deps (9b597f8ce2b97ed40bb57e55ad178cf8ce270fa9) From c316781fb709e3ced63d188c80b07a69a01969a2 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 25 Sep 2014 13:07:37 +0400 Subject: [PATCH 072/302] Update ChangeLog.md --- ChangeLog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0e4a982..45c392d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,6 @@ -## [0.4.23.beta9](https://ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...v0.4.23.beta9) +## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...master) + +* problem with calculating local varibales for 1.8 fixed ## "per-historical" changes Dennis Ushakov From 230d7739cbca2159f61977fcb17e5077799c92f7 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 25 Sep 2014 13:11:27 +0400 Subject: [PATCH 073/302] ChangeLog renamed to ChangeLog.md --- ruby-debug-ide.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby-debug-ide.gemspec b/ruby-debug-ide.gemspec index 3fa468d..00d2e45 100644 --- a/ruby-debug-ide.gemspec +++ b/ruby-debug-ide.gemspec @@ -6,7 +6,7 @@ RUBY_DEBUG_IDE_VERSION = Debugger::IDE_VERSION unless defined? RUBY_DEBUG_IDE_VE unless defined? FILES FILES = ['CHANGES', - 'ChangeLog', + 'ChangeLog.md', 'ChangeLog.archive', 'MIT-LICENSE', 'Rakefile', From ff72bf0cacbbe549aa47950b7e5ea7f41a8bec5e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 25 Sep 2014 13:14:32 +0400 Subject: [PATCH 074/302] changelog updated --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 45c392d..9122fae 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,4 @@ -## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...master) +## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...v0.4.23.beta9) * problem with calculating local varibales for 1.8 fixed From 41d03982087ac838887742afebd25bf44627bcb9 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 3 Oct 2014 16:45:14 +0400 Subject: [PATCH 075/302] RUBY-15804: not all keys are comparable so let's convert them to strings --- ChangeLog.md | 4 ++++ lib/ruby-debug-ide/version.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 9122fae..caf8af5 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta9...v0.4.23.beta10) + +* fixed problem with printing hashes [RUBY-15804](https://youtrack.jetbrains.com/issue/RUBY-15804) + ## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...v0.4.23.beta9) * problem with calculating local varibales for 1.8 fixed diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 00cd78f..21dfc1b 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta9' + IDE_VERSION='0.4.23.beta10' end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index d7cbb10..a160162 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -189,7 +189,7 @@ def build_compact_name(value_str, value) end end if value.is_a?(Hash) - slice = value.sort_by { |k,v| k }[0..5] + slice = value.sort_by { |k,v| k.to_s }[0..5] compact = slice.map {|kv| "#{kv[0]}: #{kv[1]}"}.join(", ") compact = "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end From dedc61f851978de6ab434f6f92379641e9575561 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 23 Oct 2014 19:27:03 +0400 Subject: [PATCH 076/302] Should not fail if breakpoint's file is incorrect --- ChangeLog.md | 7 ++++++- lib/ruby-debug-ide/commands/breakpoints.rb | 2 +- lib/ruby-debug-ide/version.rb | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index caf8af5..9e9911e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,9 @@ -## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta9...v0.4.23.beta10) +## [0.4.23.beta11](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta10...v0.4.23.beta11) + +* adding breakpoint in non-existing file should not break debugger + [RUBY-15873](https://youtrack.jetbrains.com/issue/RUBY-15873) + +## [0.4.23.beta10](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta9...v0.4.23.beta10) * fixed problem with printing hashes [RUBY-15804](https://youtrack.jetbrains.com/issue/RUBY-15804) diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index 5644f21..fb9fa6f 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -70,7 +70,7 @@ def realpath(filename) if (RUBY_VERSION < '1.9') || (RbConfig::CONFIG['host_os'] =~ /mswin/) filename else - File.realpath(filename) + File.realpath(filename) rescue filename end end end diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 21dfc1b..d054ec8 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta10' + IDE_VERSION='0.4.23.beta11' end From 7f5705356d285e753122232e47ee1a25673d0ba9 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Nov 2014 11:38:59 +0300 Subject: [PATCH 077/302] Need to filter out binary data from compact name https://youtrack.jetbrains.com/issue/RUBY-15960 --- lib/ruby-debug-ide/xml_printer.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index a160162..ef85350 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -170,7 +170,7 @@ def print_variable(name, value, kind) rescue end end - value_str = "[Binary Data]" if (value_str.respond_to?('is_binary_data?') && value_str.is_binary_data?) + value_str = handle_binary_data(value_str) compact_value_str = build_compact_name(value_str, value) print("", CGI.escapeHTML(name), CGI.escapeHTML(compact_value_str), kind, CGI.escapeHTML(value_str), value.class, @@ -184,13 +184,13 @@ def build_compact_name(value_str, value) if value.is_a?(Array) slice = value[0..10] compact = slice.inspect - if (value.size != slice.size) + if value.size != slice.size compact = compact[0..compact.size-2] + ", ...]" end end if value.is_a?(Hash) slice = value.sort_by { |k,v| k.to_s }[0..5] - compact = slice.map {|kv| "#{kv[0]}: #{kv[1]}"}.join(", ") + compact = slice.map {|kv| "#{kv[0]}: #{handle_binary_data(kv[1])}"}.join(", ") compact = "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end compact @@ -343,6 +343,11 @@ def print(*params) @interface.print(*params) end + def handle_binary_data(value) + return "[Binary Data]" if (value.respond_to?('is_binary_data?') && value.is_binary_data?) + value + end + instance_methods.each do |m| if m.to_s.index('print_') == 0 protect m From 3d217031e33e06333908c319b0424837ba7a9388 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 13 Nov 2014 11:39:23 +0300 Subject: [PATCH 078/302] version bumped to 0.4.23.rc1 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index d054ec8..76b67cb 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.beta11' + IDE_VERSION='0.4.23.rc1' end From 1ca1c33b1f5c969faadac4ca93dfd3cd8c8561e1 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 14 Nov 2014 13:42:33 +0300 Subject: [PATCH 079/302] Let's ignore invalid encoding too. --- lib/ruby-debug-ide/xml_printer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index ef85350..895eb44 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -344,7 +344,8 @@ def print(*params) end def handle_binary_data(value) - return "[Binary Data]" if (value.respond_to?('is_binary_data?') && value.is_binary_data?) + return '[Binary Data]' if (value.respond_to?('is_binary_data?') && value.is_binary_data?) + return '[Invalid encoding]' if (value.respond_to?('valid_encoding?') && !value.valid_encoding?) value end From 15c7a90de884604a7a7e9cf120ab6a67ccb64c5f Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 14 Nov 2014 13:54:07 +0300 Subject: [PATCH 080/302] Code cleanup: fixed RubyMine's warnings --- lib/ruby-debug-ide/xml_printer.rb | 34 +++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 895eb44..46bb8ed 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -91,8 +91,7 @@ def print_contexts(contexts) end def print_context(context) - current = 'current="yes"' if context.thread == Thread.current - print "", context.thnum, context.thread.status, Process.pid + print "", context.thnum, context.thread.status, Process.pid end def print_variables(vars, kind) @@ -147,28 +146,29 @@ def print_variable(name, value, kind) end if value.is_a?(Array) || value.is_a?(Hash) has_children = !value.empty? - unless has_children - value_str = "Empty #{value.class}" - else - size = value.size + if has_children + size = value.size value_str = "#{value.class} (#{value.size} element#{size > 1 ? "s" : "" })" + else + value_str = "Empty #{value.class}" end elsif value.is_a?(String) has_children = value.respond_to?('bytes') || value.respond_to?('encoding') value_str = value else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #$!>" + value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end end if value_str.respond_to?('encode') + # noinspection RubyEmptyRescueBlockInspection begin value_str = value_str.encode("UTF-8") rescue - end + end end value_str = handle_binary_data(value_str) compact_value_str = build_compact_name(value_str, value) @@ -189,7 +189,7 @@ def build_compact_name(value_str, value) end end if value.is_a?(Hash) - slice = value.sort_by { |k,v| k.to_s }[0..5] + slice = value.sort_by { |k, _| k.to_s }[0..5] compact = slice.map {|kv| "#{kv[0]}: #{handle_binary_data(kv[1])}"}.join(", ") compact = "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end @@ -255,7 +255,7 @@ def print_pp(value) def print_list(b, e, file, line) print "[%d, %d] in %s\n", b, e, file - if lines = Debugger.source_for(file) + if (lines = Debugger.source_for(file)) b.upto(e) do |n| if n > 0 && lines[n-1] if n == line @@ -266,7 +266,7 @@ def print_list(b, e, file, line) end end else - print "No sourcefile available for %s\n", file + print "No source-file available for %s\n", file end end @@ -280,7 +280,7 @@ def print_methods(methods) # Events - def print_breakpoint(n, breakpoint) + def print_breakpoint(_, breakpoint) print("", breakpoint.source, breakpoint.pos, Debugger.current_context.thnum) end @@ -302,7 +302,7 @@ def print_at_line(context, file, line) File.expand_path(file), line, context.thnum, context.stack_size end - def print_exception(exception, binding) + def print_exception(exception, _) print_element("variables") do proxy = ExceptionProxy.new(exception) InspectCommand.reference_result(proxy) @@ -349,6 +349,14 @@ def handle_binary_data(value) value end + def current_thread_attr + if context.thread == Thread.current + 'current="yes"' + else + '' + end + end + instance_methods.each do |m| if m.to_s.index('print_') == 0 protect m From fbc485a2f230cfcc82912375bddeae993811bccc Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 14 Nov 2014 19:57:19 +0300 Subject: [PATCH 081/302] Fixing refactoring's bug --- lib/ruby-debug-ide/xml_printer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 46bb8ed..e4660b0 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -91,7 +91,7 @@ def print_contexts(contexts) end def print_context(context) - print "", context.thnum, context.thread.status, Process.pid + print "", context.thnum, context.thread.status, Process.pid end def print_variables(vars, kind) @@ -349,7 +349,7 @@ def handle_binary_data(value) value end - def current_thread_attr + def current_thread_attr(context) if context.thread == Thread.current 'current="yes"' else From 67f274ac09a5009f91dc34243907d954784f5a82 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 17 Nov 2014 13:13:52 +0300 Subject: [PATCH 082/302] version bumped to 0.4.23 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 76b67cb..f84dfc8 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23.rc1' + IDE_VERSION='0.4.23' end From bad1586333dcbe7f66247accf6c108ffd06ca092 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 17 Nov 2014 13:17:34 +0300 Subject: [PATCH 083/302] Changelog updated --- ChangeLog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 9e9911e..a80eaf3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.23](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta11...v0.4.23) + +* fixed problem with compact name for binary params (strings with invalid encoding) + [RUBY-15960](https://youtrack.jetbrains.com/issue/RUBY-15960) + ## [0.4.23.beta11](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta10...v0.4.23.beta11) * adding breakpoint in non-existing file should not break debugger From d4ea2cfccae13a0f39cb15c96c7504eb3db2f0d1 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 4 Dec 2014 12:53:34 +0300 Subject: [PATCH 084/302] RubyMine's warning fixed --- lib/ruby-debug-ide/xml_printer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index e4660b0..32db009 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -298,7 +298,7 @@ def print_trace(context, file, line) end def print_at_line(context, file, line) - print "", + print "", File.expand_path(file), line, context.thnum, context.stack_size end @@ -344,6 +344,7 @@ def print(*params) end def handle_binary_data(value) + # noinspection RubyResolve return '[Binary Data]' if (value.respond_to?('is_binary_data?') && value.is_binary_data?) return '[Invalid encoding]' if (value.respond_to?('valid_encoding?') && !value.valid_encoding?) value From 0d1ec96d7d42e17c31415a99f27f933cb7e728e8 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 4 Dec 2014 12:55:15 +0300 Subject: [PATCH 085/302] performance: do not need to escape the same string value twice --- lib/ruby-debug-ide/xml_printer.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 32db009..1adf314 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -172,10 +172,11 @@ def print_variable(name, value, kind) end value_str = handle_binary_data(value_str) compact_value_str = build_compact_name(value_str, value) + escaped_value_str = CGI.escapeHTML(value_str) print("", - CGI.escapeHTML(name), CGI.escapeHTML(compact_value_str), kind, CGI.escapeHTML(value_str), value.class, + CGI.escapeHTML(name), CGI.escapeHTML(compact_value_str), kind, escaped_value_str, value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) - print("", CGI.escapeHTML(value_str)) + print("", escaped_value_str) print('') end From 84e93e332816f04784bf15d0fcb370d3c81c5d5d Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 4 Dec 2014 13:01:57 +0300 Subject: [PATCH 086/302] #build_compact_name refactored and made private --- lib/ruby-debug-ide/xml_printer.rb | 38 +++++++++++++++++-------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 1adf314..59f40a7 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -180,23 +180,6 @@ def print_variable(name, value, kind) print('') end - def build_compact_name(value_str, value) - compact = value_str - if value.is_a?(Array) - slice = value[0..10] - compact = slice.inspect - if value.size != slice.size - compact = compact[0..compact.size-2] + ", ...]" - end - end - if value.is_a?(Hash) - slice = value.sort_by { |k, _| k.to_s }[0..5] - compact = slice.map {|kv| "#{kv[0]}: #{handle_binary_data(kv[1])}"}.join(", ") - compact = "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" - end - compact - end - def print_breakpoints(breakpoints) print_element 'breakpoints' do breakpoints.sort_by{|b| b.id }.each do |b| @@ -359,6 +342,27 @@ def current_thread_attr(context) end end + def build_compact_name(value_str, value) + return compact_array_str(value) if value.is_a?(Array) + return compact_hash_str(value) if value.is_a?(Hash) + value_str + end + + def compact_array_str(value) + slice = value[0..10] + compact = slice.inspect + if value.size != slice.size + compact[0..compact.size-2] + ", ...]" + end + compact + end + + def compact_hash_str(value) + slice = value.sort_by { |k, _| k.to_s }[0..5] + compact = slice.map { |kv| "#{kv[0]}: #{handle_binary_data(kv[1])}" }.join(", ") + "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" + end + instance_methods.each do |m| if m.to_s.index('print_') == 0 protect m From 2839e5e6c741ef8d6060115c6561d96dc28b82a5 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 4 Dec 2014 13:08:38 +0300 Subject: [PATCH 087/302] performance: let's do no add compactValue attr if it is the same as regular value --- lib/ruby-debug-ide/xml_printer.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 59f40a7..a26f3f4 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -171,10 +171,9 @@ def print_variable(name, value, kind) end end value_str = handle_binary_data(value_str) - compact_value_str = build_compact_name(value_str, value) escaped_value_str = CGI.escapeHTML(value_str) - print("", - CGI.escapeHTML(name), CGI.escapeHTML(compact_value_str), kind, escaped_value_str, value.class, + print("", + CGI.escapeHTML(name), build_compact_value_attr(value), kind, escaped_value_str, value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) print("", escaped_value_str) print('') @@ -342,10 +341,10 @@ def current_thread_attr(context) end end - def build_compact_name(value_str, value) + def build_compact_name(value) return compact_array_str(value) if value.is_a?(Array) return compact_hash_str(value) if value.is_a?(Hash) - value_str + nil end def compact_array_str(value) @@ -363,6 +362,11 @@ def compact_hash_str(value) "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end + def build_compact_value_attr(value) + compact_value_str = build_compact_name(value) + compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\"" + end + instance_methods.each do |m| if m.to_s.index('print_') == 0 protect m From 4c3728a44a72ce5ba5720604a2c47c21d5cbdb1c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 4 Dec 2014 13:09:38 +0300 Subject: [PATCH 088/302] version bumped up to 0.4.24.beta2 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index f84dfc8..9914e2c 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.23' + IDE_VERSION='0.4.24.beta2' end From e52743deb344bf03a2e8790c40d6c74afed26060 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 13:32:54 +0300 Subject: [PATCH 089/302] version bumped up (0.4.24.beta4) --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 9914e2c..19f963a 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.24.beta2' + IDE_VERSION='0.4.24.beta4' end From a655fb41df6843578dd8c5bff692bb47954a132c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 13:33:40 +0300 Subject: [PATCH 090/302] Added command line param to enable RM-specific incompatible protocol changes --- bin/rdebug-ide | 7 ++++++- lib/ruby-debug-ide/xml_printer.rb | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 888ce5c..9361b7b 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -19,7 +19,8 @@ options = OpenStruct.new( 'tracing' => false, 'int_handler' => true, 'dispatcher_port' => -1, - 'evaluation_timeout' => 10 + 'evaluation_timeout' => 10, + 'rm_protocol_extensions' => false ) opts = OptionParser.new do |opts| @@ -54,6 +55,9 @@ EOB opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true} opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false} + opts.on("--rubymine-protocol-extensions", "Enable RubyMine-specific incompatible protocol extensions") do + options.rm_protocol_extensions = true + end opts.separator "" opts.separator "Common options:" opts.on_tail("-v", "--version", "Show version") do @@ -112,6 +116,7 @@ end Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing Debugger.evaluation_timeout = options.evaluation_timeout +Debugger.rm_protocol_extensions = options.rm_protocol_extensions Debugger.debug_program(options) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index a26f3f4..fc3d6b7 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -78,7 +78,7 @@ def print_current_frame(frame_pos) def print_frame(context, frame_id, current_frame_id) # idx + 1: one-based numbering as classic-debugger file = context.frame_file(frame_id) - print "", + print "", frame_id + 1, File.expand_path(file), context.frame_line(frame_id) end @@ -173,9 +173,9 @@ def print_variable(name, value, kind) value_str = handle_binary_data(value_str) escaped_value_str = CGI.escapeHTML(value_str) print("", - CGI.escapeHTML(name), build_compact_value_attr(value), kind, escaped_value_str, value.class, + CGI.escapeHTML(name), build_compact_value_attr(value), kind, build_value_attr(escaped_value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) - print("", escaped_value_str) + print("", escaped_value_str) if Debugger.rm_protocol_extensions print('') end @@ -367,6 +367,10 @@ def build_compact_value_attr(value) compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\"" end + def build_value_attr(escaped_value_str) + Debugger.rm_protocol_extensions ? '' : escaped_value_str + end + instance_methods.each do |m| if m.to_s.index('print_') == 0 protect m From 3ac6814ef7220cbecf8a234857b25b86f21d5f09 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 13:34:00 +0300 Subject: [PATCH 091/302] Code cleanup: couple RM's warnings fixed --- lib/ruby-debug-ide/ide_processor.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index 549d230..95d1841 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -28,13 +28,13 @@ def process_commands s.interface = @interface end event_cmds = Command.commands.map{|cmd| cmd.new(state, @printer) } - while !state.proceed? do + until state.proceed? do input = @interface.command_queue.pop catch(:debug_error) do splitter[input].each do |input| # escape % since print_debug might use printf @printer.print_debug "Processing in context: #{input.gsub('%', '%%')}" - if cmd = event_cmds.find { |c| c.match(input) } + if (cmd = event_cmds.find { |c| c.match(input) }) if context.dead? && cmd.class.need_context @printer.print_msg "Command is unavailable\n" else @@ -42,7 +42,7 @@ def process_commands end else @printer.print_msg "Unknown command: #{input}" - end + end end end state.restore_context From 20a3a3cb995b859a18fee0ed25438f7c3ca73d00 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 13:53:30 +0300 Subject: [PATCH 092/302] Need to declare Debugger.rm_protocol_extensions --- lib/ruby-debug-ide.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 3853852..0135bff 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -41,7 +41,7 @@ def cleanup_backtrace(backtrace) cleared end - attr_accessor :cli_debug, :xml_debug, :evaluation_timeout + attr_accessor :cli_debug, :xml_debug, :evaluation_timeout, :rm_protocol_extensions attr_accessor :control_thread attr_reader :interface From 7ce89722f8208e1603196f965203832a868d80de Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 17:16:37 +0300 Subject: [PATCH 093/302] There is Debugger::Exception thus to rescue ::Exception we have to use fqn --- lib/ruby-debug-ide/ide_processor.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index 549d230..ab05df3 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -47,10 +47,7 @@ def process_commands end state.restore_context end - rescue IOError, SystemCallError - @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil - @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil - rescue Exception + rescue ::Exception @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil end From 47f1c3bc405738e7a5a85311589e02c94c83b5b2 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 17:29:31 +0300 Subject: [PATCH 094/302] String#== is always defined Some FactoryGirl's classes return non-string object from #to_s and those objects can not compare themselves with strings :( --- lib/ruby-debug-ide/commands/variables.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index 3414fcf..331c72b 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -129,7 +129,7 @@ def execute locals = @state.context.frame_locals(@state.frame_pos) _self = @state.context.frame_self(@state.frame_pos) begin - locals['self'] = _self unless _self.to_s == "main" + locals['self'] = _self unless "main" == _self.to_s rescue => ex locals['self'] = "" $stderr << "Cannot evaluate self\n#{ex.class.name}: #{ex.message}\n #{ex.backtrace.join("\n ")}" From cfce332be4d8d2847edf94b89fa140b23c8953f6 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 8 Dec 2014 17:35:46 +0300 Subject: [PATCH 095/302] If any problem occurred then compact name should be nil --- lib/ruby-debug-ide/xml_printer.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index fc3d6b7..63d9fe9 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -354,12 +354,16 @@ def compact_array_str(value) compact[0..compact.size-2] + ", ...]" end compact + rescue + nil end def compact_hash_str(value) slice = value.sort_by { |k, _| k.to_s }[0..5] compact = slice.map { |kv| "#{kv[0]}: #{handle_binary_data(kv[1])}" }.join(", ") "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" + rescue + nil end def build_compact_value_attr(value) From c38e7c0bc66132ab777e7ac202776d59909ce0a1 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 10 Dec 2014 14:39:50 +0300 Subject: [PATCH 096/302] It is #build_compact_name who is responsible for rescuing all exception. --- lib/ruby-debug-ide/xml_printer.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 63d9fe9..1c838f0 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -345,6 +345,9 @@ def build_compact_name(value) return compact_array_str(value) if value.is_a?(Array) return compact_hash_str(value) if value.is_a?(Hash) nil + rescue ::Exception => e + print_debug(e) + nil end def compact_array_str(value) @@ -354,16 +357,12 @@ def compact_array_str(value) compact[0..compact.size-2] + ", ...]" end compact - rescue - nil end def compact_hash_str(value) slice = value.sort_by { |k, _| k.to_s }[0..5] compact = slice.map { |kv| "#{kv[0]}: #{handle_binary_data(kv[1])}" }.join(", ") "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" - rescue - nil end def build_compact_value_attr(value) From e40ead9b268584fda0e6826e45fe5a3e14b7c901 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 10 Dec 2014 15:07:29 +0300 Subject: [PATCH 097/302] Change log updated --- ChangeLog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index a80eaf3..427bae7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,9 @@ +## [0.4.24.beta4](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23...v0.4.24.beta4) + +* Performance optimisation for variable representation [RUBY-16055](https://youtrack.jetbrains.com/issue/RUBY-16055) +* Added command line argument to enable RubyMine-specific protocol extensions +* Several fixes to make debugger more robust [RUBY-16070](https://youtrack.jetbrains.com/issue/RUBY-16070) + ## [0.4.23](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta11...v0.4.23) * fixed problem with compact name for binary params (strings with invalid encoding) From 1f6c943a87fe7e8f8e0d1611fafdd72108dac9d7 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 10 Dec 2014 16:07:07 +0300 Subject: [PATCH 098/302] Do not print empty value attr for variable if not needed In case RubyMine-specific protocol extensions are enabled we do not need to print value attr at all --- ChangeLog.md | 4 ++++ lib/ruby-debug-ide/version.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 427bae7..f84507e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +## [0.4.24.beta5](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.24.beta4...v0.4.24.beta5) + +* do not print empty value attr in case RubyMine-specific protocol extensions are enabled + ## [0.4.24.beta4](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23...v0.4.24.beta4) * Performance optimisation for variable representation [RUBY-16055](https://youtrack.jetbrains.com/issue/RUBY-16055) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 19f963a..c7d9d49 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.24.beta4' + IDE_VERSION='0.4.24.beta5' end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 1c838f0..2ee80ff 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -172,7 +172,7 @@ def print_variable(name, value, kind) end value_str = handle_binary_data(value_str) escaped_value_str = CGI.escapeHTML(value_str) - print("", + print("", CGI.escapeHTML(name), build_compact_value_attr(value), kind, build_value_attr(escaped_value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) print("", escaped_value_str) if Debugger.rm_protocol_extensions @@ -371,7 +371,7 @@ def build_compact_value_attr(value) end def build_value_attr(escaped_value_str) - Debugger.rm_protocol_extensions ? '' : escaped_value_str + Debugger.rm_protocol_extensions ? '' : "value=\"#{escaped_value_str}\"" end instance_methods.each do |m| From 49b2e54d8a7648689a2ba694d3239d36a98f104f Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Dec 2014 08:25:18 +0300 Subject: [PATCH 099/302] Need to use ::Exception to avoid name clashing with ::Debugger::Exception --- lib/ruby-debug-ide/ide_processor.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index 2747782..e5b7e98 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -90,11 +90,7 @@ def process_commands end end end - rescue IOError, SystemCallError - @printer.print_debug "INTERNAL ERROR!!! #{$!}\n" - @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil - @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil - rescue Exception + rescue ::Exception @printer.print_debug "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error "INTERNAL ERROR!!! #{$!}\n" rescue nil @printer.print_error $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil From 6f90571a7ac3929b2de73dd4d1617441d1e9dbc9 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Dec 2014 08:25:51 +0300 Subject: [PATCH 100/302] Version bumped up to 0.4.24.beta6 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index c7d9d49..c48e9e9 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.24.beta5' + IDE_VERSION='0.4.24.beta6' end From d49128a521dc2f481291928f0a7ac346b39faa5d Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Dec 2014 08:27:16 +0300 Subject: [PATCH 101/302] Let's make it a release version 0.4.24 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index c48e9e9..48e255b 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.24.beta6' + IDE_VERSION='0.4.24' end From 89823bdc49c68bb5ad32d9a558f71790b444c5be Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Dec 2014 08:28:31 +0300 Subject: [PATCH 102/302] Change log updated --- ChangeLog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index f84507e..5df7ab7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +## [0.4.24](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.24.beta5...v0.4.24) + +* time to release + ## [0.4.24.beta5](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.24.beta4...v0.4.24.beta5) * do not print empty value attr in case RubyMine-specific protocol extensions are enabled From 72566e9ad8e074a0ccd3c7f016f7e95aedb92362 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Dec 2014 08:48:24 +0300 Subject: [PATCH 103/302] Typo fixed --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 5df7ab7..79997de 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -28,7 +28,7 @@ ## [0.4.23.beta9](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.23.beta8...v0.4.23.beta9) -* problem with calculating local varibales for 1.8 fixed +* problem with calculating local variables for 1.8 fixed ## "per-historical" changes Dennis Ushakov From 435c08ef89d998ab4896c68f3040c2f505630e8a Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 16 Dec 2014 08:49:13 +0300 Subject: [PATCH 104/302] Version bumped up to 0.4.25-pre1 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 48e255b..cc97fe7 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.24' + IDE_VERSION='0.4.25-pre1' end From db3d0da2256f0333d6e1bab39eebf05939a9b3e7 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 20 Jan 2015 11:53:43 +0300 Subject: [PATCH 105/302] Fixed several warning reported by RubyMine --- lib/ruby-debug-ide/commands/variables.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index 331c72b..cc8d935 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -80,11 +80,11 @@ def execute obj = debug_eval(@match.post_match) end return unless obj - if (obj.is_a?(Array)) then + if obj.is_a?(Array) print_array(obj) - elsif (obj.is_a?(Hash)) then + elsif obj.is_a?(Hash) print_hash(obj) - elsif (obj.is_a?(String)) + elsif obj.is_a?(String) print_string(obj) else print_element("variables") do From 85ee719a024c7fd18d67704e2784b13fdc658c2b Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 20 Jan 2015 11:54:37 +0300 Subject: [PATCH 106/302] Let's use String#inspect instead of #to_s for string variables. see https://youtrack.jetbrains.com/issue/RUBY-16192 --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 2ee80ff..c568e0d 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -154,7 +154,7 @@ def print_variable(name, value, kind) end elsif value.is_a?(String) has_children = value.respond_to?('bytes') || value.respond_to?('encoding') - value_str = value + value_str = value.inspect else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" From 5a6875978d0a8314b5e39b835220471d054869aa Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 20 Jan 2015 11:55:03 +0300 Subject: [PATCH 107/302] Time to release 0.4.25 --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 79997de..9229493 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.25](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.24...v0.4.25) + +* Let's use String#inspect in print variable for String variables + [RUBY-16192](https://youtrack.jetbrains.com/issue/RUBY-16192) + ## [0.4.24](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.24.beta5...v0.4.24) * time to release diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index cc97fe7..874df99 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.25-pre1' + IDE_VERSION='0.4.25' end From a96a0af08f528ed402702e60dba13d9f64ea957e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 30 Jan 2015 12:44:47 +0300 Subject: [PATCH 108/302] File name should be html-escaped --- lib/ruby-debug-ide/xml_printer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index c568e0d..336340d 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -79,7 +79,7 @@ def print_frame(context, frame_id, current_frame_id) # idx + 1: one-based numbering as classic-debugger file = context.frame_file(frame_id) print "", - frame_id + 1, File.expand_path(file), context.frame_line(frame_id) + frame_id + 1, CGI.escapeHTML(File.expand_path(file)), context.frame_line(frame_id) end def print_contexts(contexts) @@ -282,7 +282,7 @@ def print_trace(context, file, line) def print_at_line(context, file, line) print "", - File.expand_path(file), line, context.thnum, context.stack_size + CGI.escapeHTML(File.expand_path(file)), line, context.thnum, context.stack_size end def print_exception(exception, _) From 1fae8cfe82d54a446559dc43fe212d14e9fe1951 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 6 Feb 2015 07:56:30 +0300 Subject: [PATCH 109/302] Compact name should be compact If string representation of a value is too long let's cut it to make compact value --- lib/ruby-debug-ide/xml_printer.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 336340d..b259c16 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -173,7 +173,8 @@ def print_variable(name, value, kind) value_str = handle_binary_data(value_str) escaped_value_str = CGI.escapeHTML(value_str) print("", - CGI.escapeHTML(name), build_compact_value_attr(value), kind, build_value_attr(escaped_value_str), value.class, + CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, + build_value_attr(escaped_value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) print("", escaped_value_str) if Debugger.rm_protocol_extensions print('') @@ -341,15 +342,21 @@ def current_thread_attr(context) end end - def build_compact_name(value) + def build_compact_name(value, value_str) return compact_array_str(value) if value.is_a?(Array) return compact_hash_str(value) if value.is_a?(Hash) + return value_str[0..max_compact_name_size - 3] + '...' if value_str.size > max_compact_name_size nil rescue ::Exception => e print_debug(e) nil end + def max_compact_name_size + # todo: do we want to configure it? + 50 + end + def compact_array_str(value) slice = value[0..10] compact = slice.inspect @@ -365,8 +372,8 @@ def compact_hash_str(value) "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end - def build_compact_value_attr(value) - compact_value_str = build_compact_name(value) + def build_compact_value_attr(value, value_str) + compact_value_str = build_compact_name(value, value_str) compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\"" end From 91690353bcae7fb61203fc99437577bcd04ff037 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 6 Feb 2015 08:00:22 +0300 Subject: [PATCH 110/302] Version bumped up --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 9229493..92eb289 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.26](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.25...v0.4.26) + +* Compact value for inline debugger should be really compact + [RUBY-15932](https://youtrack.jetbrains.com/issue/RUBY-15932) + ## [0.4.25](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.24...v0.4.25) * Let's use String#inspect in print variable for String variables diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 874df99..87965a5 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.25' + IDE_VERSION='0.4.26' end From 83a7a2ffcb3e3e36be288eb780187b7f3068d81e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 16 Feb 2015 14:15:58 +0300 Subject: [PATCH 111/302] RUBY-16275: extra quotes should be removed from string variable's representation --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/version.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 92eb289..faeecbb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.27](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.26...v0.4.27) + +* Redundant quotes dropped from string variable representation + [RUBY-16275](https://youtrack.jetbrains.com/issue/RUBY-16275) + ## [0.4.26](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.25...v0.4.26) * Compact value for inline debugger should be really compact diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 87965a5..a174250 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.26' + IDE_VERSION='0.4.27' end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index b259c16..6d4699d 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -154,7 +154,7 @@ def print_variable(name, value, kind) end elsif value.is_a?(String) has_children = value.respond_to?('bytes') || value.respond_to?('encoding') - value_str = value.inspect + value_str = value.inspect[1..-2] else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" From 6d58999b473b4b94115b12c91821ecebe336fe30 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 2 Mar 2015 19:54:56 +0300 Subject: [PATCH 112/302] Expect escaped backslashes in expressions to inspect --- lib/ruby-debug-ide/command.rb | 7 ++++++- .../commands/expression_info.rb | 2 +- test-base/inspect_test.rb | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index ff09273..d2d993b 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -108,8 +108,8 @@ def timeout(sec) def debug_eval(str, b = get_binding) begin str = str.to_s + to_inspect = unescape_incoming(str) max_time = Debugger.evaluation_timeout - to_inspect = str.gsub(/\\n/, "\n") @printer.print_debug("Evaluating #{str} with timeout after %i sec", max_time) timeout(max_time) do eval(to_inspect, b) @@ -120,6 +120,11 @@ def debug_eval(str, b = get_binding) end end + def unescape_incoming(str) + str.gsub(/(?(?:^|[^\\])(?:\\\\)*)\\n/, "\\k\n") + .gsub(/\\\\/, '\\') + end + def debug_silent_eval(str) begin str = str.to_s diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index d2ca641..ef116f9 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -9,7 +9,7 @@ def regexp end def execute - string_to_parse = @match.post_match.gsub("\\n", "\n") + "\n\n\n" + string_to_parse = unescape_incoming(@match.post_match) + "\n\n\n" total_lines = string_to_parse.count("\n") + 1 lexer = RubyLex.new diff --git a/test-base/inspect_test.rb b/test-base/inspect_test.rb index 013b4a5..86319cf 100644 --- a/test-base/inspect_test.rb +++ b/test-base/inspect_test.rb @@ -68,5 +68,25 @@ def test_inspect_multiline_expression send_cont end + def test_inspect_escaping_escaped_newlines + create_socket ["sleep 0.1"] + run_to_line(1) + + send_ruby('v inspect "\\\\n".size') + variable = read_variables + assert_equal(1, variables.length, "There is one variable returned.") + assert_equal(1, variables[0].value, "There is one char (newline)") + + send_ruby('v inspect "\\\\\\n".size') + variable = read_variables + assert_equal(1, variables.length, "There is one variable returned.") + assert_equal(0, variables[0].value, "There are no chars, it's line continuation here") + + send_ruby('v inspect "\\\\\\\\\\n".size') + variable = read_variables + assert_equal(1, variables.length, "There is one variable returned.") + assert_equal(2, variables[0].value, "There are two chars: escaped backslash and newline") + end + end From 3d07d6ba8e564647a8410955332da685e9e3124e Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 2 Mar 2015 20:13:46 +0300 Subject: [PATCH 113/302] version up --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index a174250..18b4f9b 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.27' + IDE_VERSION='0.4.28' end From 62f44c69bd02ad006f4718e8a1eaea73f0b4d530 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 3 Mar 2015 16:54:46 +0300 Subject: [PATCH 114/302] unit-testing of incoming unescaping, fixed inspect test --- lib/ruby-debug-ide/command.rb | 14 +++++----- test-base/inspect_test.rb | 21 +++++++++----- test/ruby-debug/unescape_incoming_test.rb | 34 +++++++++++++++++++++++ 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 test/ruby-debug/unescape_incoming_test.rb diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index d2d993b..4c70bbf 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -64,6 +64,11 @@ def method_missing(meth, *args, &block) def options @options ||= {} end + + def unescape_incoming(str) + str.gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n") + .gsub(/\\\\/, '\\') + end end def initialize(state, printer) @@ -104,11 +109,11 @@ def timeout(sec) y.kill if y and y.alive? end end - + def debug_eval(str, b = get_binding) begin str = str.to_s - to_inspect = unescape_incoming(str) + to_inspect = Command.unescape_incoming(str) max_time = Debugger.evaluation_timeout @printer.print_debug("Evaluating #{str} with timeout after %i sec", max_time) timeout(max_time) do @@ -120,11 +125,6 @@ def debug_eval(str, b = get_binding) end end - def unescape_incoming(str) - str.gsub(/(?(?:^|[^\\])(?:\\\\)*)\\n/, "\\k\n") - .gsub(/\\\\/, '\\') - end - def debug_silent_eval(str) begin str = str.to_s diff --git a/test-base/inspect_test.rb b/test-base/inspect_test.rb index 86319cf..ca57de8 100644 --- a/test-base/inspect_test.rb +++ b/test-base/inspect_test.rb @@ -68,24 +68,31 @@ def test_inspect_multiline_expression send_cont end - def test_inspect_escaping_escaped_newlines + def test_inspect_unescaping_escaped_newlines create_socket ["sleep 0.1"] run_to_line(1) send_ruby('v inspect "\\\\n".size') - variable = read_variables + variables = read_variables assert_equal(1, variables.length, "There is one variable returned.") - assert_equal(1, variables[0].value, "There is one char (newline)") + assert_equal("1", variables[0].value, "There is one char (newline)") send_ruby('v inspect "\\\\\\n".size') - variable = read_variables + variables = read_variables assert_equal(1, variables.length, "There is one variable returned.") - assert_equal(0, variables[0].value, "There are no chars, it's line continuation here") + assert_equal("0", variables[0].value, "There are no chars, it's line continuation here") send_ruby('v inspect "\\\\\\\\\\n".size') - variable = read_variables + variables = read_variables + assert_equal(1, variables.length, "There is one variable returned.") + assert_equal("2", variables[0].value, "There are two chars: escaped backslash and newline") + + send_ruby('v inspect \'"\\\\n\'.size') + variables = read_variables assert_equal(1, variables.length, "There is one variable returned.") - assert_equal(2, variables[0].value, "There are two chars: escaped backslash and newline") + assert_equal("3", variables[0].value, "There are three chars: quote, backslash and n") + + send_cont end end diff --git a/test/ruby-debug/unescape_incoming_test.rb b/test/ruby-debug/unescape_incoming_test.rb new file mode 100644 index 0000000..0ac9488 --- /dev/null +++ b/test/ruby-debug/unescape_incoming_test.rb @@ -0,0 +1,34 @@ +require 'test/unit' +require 'ruby-debug-ide/command' + +class UnescaperTest < Test::Unit::TestCase + + def test_empty + do_test('', '') + do_test('a', 'a') + end + + def test_newline + do_test('\n', "\n") + do_test('a\n', "a\n") + end + + def test_escaped_newline + do_test('\\\\n', '\n') + do_test('a\\\\n', 'a\n') + end + + def test_backslash_and_newline + do_test('\\\\\\n', "\\\n") + do_test('a\\\\\\n', "a\\\n") + end + + def test_something + do_test('hello\nthere\\\\n', "hello\nthere\\n") + do_test('"\\\\\\n".size', "\"\\\n\".size") + end + + def do_test(input, expected_result) + assert_equal(expected_result, Debugger::Command.unescape_incoming(input)) + end +end \ No newline at end of file From b59de9a9bbd7950a250f7d514674329348900c5a Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 3 Mar 2015 17:52:25 +0300 Subject: [PATCH 115/302] fix chain call for ruby 1.8 --- lib/ruby-debug-ide/command.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 4c70bbf..d37b6ef 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -66,8 +66,8 @@ def options end def unescape_incoming(str) - str.gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n") - .gsub(/\\\\/, '\\') + str.gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n"). + gsub(/\\\\/, '\\') end end From 5c4cb62e90dfbb4bfae451116e8d41f98be1fc0b Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 3 Mar 2015 20:21:31 +0300 Subject: [PATCH 116/302] Fix expression_info command failing with new unescaping; Fix expression_info for ruby 1.8 --- .../commands/expression_info.rb | 13 +++++-- test-base/expression_info_test.rb | 39 +++++++++++++++++++ test-base/readers.rb | 12 ++++++ test/rd_expression_info_test.rb | 11 ++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 test-base/expression_info_test.rb create mode 100644 test/rd_expression_info_test.rb diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index ef116f9..51bc7e5 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -9,13 +9,20 @@ def regexp end def execute - string_to_parse = unescape_incoming(@match.post_match) + "\n\n\n" + string_to_parse = Command.unescape_incoming(@match.post_match) + "\n\n\n" total_lines = string_to_parse.count("\n") + 1 lexer = RubyLex.new io = StringIO.new(string_to_parse) + + begin + encoding = string_to_parse.encoding + rescue + encoding = 'None' + end + # for passing to the lexer - io.instance_exec(string_to_parse.encoding) do |string_encoding| + io.instance_exec(encoding) do |string_encoding| @my_encoding = string_encoding def self.encoding @my_encoding @@ -39,7 +46,7 @@ def self.encoding end incomplete = true - if /\A\s*\Z/m =~ last_statement[0] + if /\A\s*\Z/m =~ last_statement incomplete = false end diff --git a/test-base/expression_info_test.rb b/test-base/expression_info_test.rb new file mode 100644 index 0000000..a31ad52 --- /dev/null +++ b/test-base/expression_info_test.rb @@ -0,0 +1,39 @@ +#!/usr/bin/env ruby + +$:.unshift File.join(File.dirname(__FILE__), "..", "lib") + +require 'test_base' + +module ExpressionInfoTest + + def test_info_multiline_expression + create_socket ["sleep 0.1"] + run_to_line(1) + send_ruby('expression_info 1+') + expression_info = read_expression_info + assert_equal("true", expression_info.incomplete) + + send_ruby('expression_info 1+\\n1') + expression_info = read_expression_info + assert_equal("false", expression_info.incomplete) + + send_ruby('expression_info "') + expression_info = read_expression_info + assert_equal("true", expression_info.incomplete) + + send_ruby('expression_info "\\\\"') + expression_info = read_expression_info + assert_equal("true", expression_info.incomplete) + + send_ruby('expression_info "\\\\\\n"') + expression_info = read_expression_info + assert_equal("false", expression_info.incomplete) + + send_ruby('expression_info def my_meth') + expression_info = read_expression_info + assert_equal("true", expression_info.incomplete) + send_cont + end + +end + diff --git a/test-base/readers.rb b/test-base/readers.rb index d2f4405..483f2b5 100644 --- a/test-base/readers.rb +++ b/test-base/readers.rb @@ -19,6 +19,7 @@ module Readers RubyThread = Struct.new("RubyThread", :id, :status) Frame = Struct.new("Frame", :no, :file, :line) Variable = Struct.new("Variable", :name, :kind, :value, :type, :hasChildren, :objectId) + ExpressionInfo = Struct.new("ExpressionInfo", :incomplete, :prompt, :indent) def read_breakpoint_added (@breakpoint_added_reader ||= BreakPointAddedReader.new(parser)).read @@ -88,6 +89,10 @@ def read_processing_exception (@processing_exception_reader ||= ProcessingExceptionReader.new(parser)).read end + def read_expression_info + (@expression_info_reader ||= ExpressionInfoReader.new(parser)).read + end + def parser fail '"parser" method must be defined' end @@ -315,4 +320,11 @@ def read end end + class ExpressionInfoReader < BaseReader + def read + data = read_element_data("expressionInfo") + ExpressionInfo.new(data['incomplete'], data['prompt'], data['indent']) + end + end + end diff --git a/test/rd_expression_info_test.rb b/test/rd_expression_info_test.rb new file mode 100644 index 0000000..b5d823d --- /dev/null +++ b/test/rd_expression_info_test.rb @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby + +require 'rd_test_base' +require 'expression_info_test' + +class RDExpressionInfoTest < RDTestBase + + include ExpressionInfoTest + +end + From 314460a91b43e898dcec8b3a6c6ffc9b344e8724 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 4 Mar 2015 19:56:09 +0300 Subject: [PATCH 117/302] Don't def encoding method for StringIO if ruby 1.8 --- .../commands/expression_info.rb | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index 51bc7e5..795ca2d 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -13,23 +13,7 @@ def execute total_lines = string_to_parse.count("\n") + 1 lexer = RubyLex.new - io = StringIO.new(string_to_parse) - - begin - encoding = string_to_parse.encoding - rescue - encoding = 'None' - end - - # for passing to the lexer - io.instance_exec(encoding) do |string_encoding| - @my_encoding = string_encoding - def self.encoding - @my_encoding - end - end - - lexer.set_input(io) + lexer.set_input(create_io_reader(string_to_parse)) last_statement = '' last_prompt = '' @@ -53,6 +37,21 @@ def self.encoding @printer.print_expression_info(incomplete, last_prompt, last_indent) end + def create_io_reader(string_to_parse) + io = StringIO.new(string_to_parse) + + if string_to_parse.respond_to?(:encoding) + io.instance_exec(string_to_parse.encoding) do |string_encoding| + @my_encoding = string_encoding + def self.encoding + @my_encoding + end + end + end + + io + end + class << self def help_command "expression_info" From 11f43c6f12e41c1622320303931957c0219b171a Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 6 Mar 2015 18:34:34 +0300 Subject: [PATCH 118/302] Changelog updated --- ChangeLog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index faeecbb..951aeef 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +## [0.4.28](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.27...v0.4.28) + +* [better handling for escaped chars and slashes](https://github.com/ruby-debug/ruby-debug-ide/pull/68) + ## [0.4.27](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.26...v0.4.27) * Redundant quotes dropped from string variable representation From aad9cd2fa190764f3e851c6a90389fdb5dee0697 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 16 Apr 2015 15:11:04 +0300 Subject: [PATCH 119/302] Do not mix string interpolation and string formats (unless you have to) --- lib/ruby-debug-ide/command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index d37b6ef..bc036b8 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -115,7 +115,7 @@ def debug_eval(str, b = get_binding) str = str.to_s to_inspect = Command.unescape_incoming(str) max_time = Debugger.evaluation_timeout - @printer.print_debug("Evaluating #{str} with timeout after %i sec", max_time) + @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time) timeout(max_time) do eval(to_inspect, b) end From 8f0472488eb30b2ec781879df6b2df1429634527 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 16 Apr 2015 15:15:45 +0300 Subject: [PATCH 120/302] Preparation for a new release (0.4.29) --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 951aeef..1fc984c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.29](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.28...v0.4.29) + +* Fixed problem with evaluating "%" + [RUBY-16244](https://youtrack.jetbrains.com/issue/RUBY-16244) + ## [0.4.28](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.27...v0.4.28) * [better handling for escaped chars and slashes](https://github.com/ruby-debug/ruby-debug-ide/pull/68) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 18b4f9b..978c177 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.28' + IDE_VERSION='0.4.29' end From b6c5ba29e3ffb4dc8c3258f15a6943b6804fb997 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Apr 2015 14:49:28 +0300 Subject: [PATCH 121/302] version bumped up to 0.4.30 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 978c177..2e94623 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.29' + IDE_VERSION='0.4.30' end From 26fbd6a2e553c968edb83d096603376be67cb3ea Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Apr 2015 14:50:18 +0300 Subject: [PATCH 122/302] More complicated gsub to handle empty lines' unescaping correctly --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/command.rb | 5 +++-- test/ruby-debug/unescape_incoming_test.rb | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 1fc984c..b30feb0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.30](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.29...v0.4.30) + +* unescaping of empty line fixed + [RUBY-16600](https://youtrack.jetbrains.com/issue/RUBY-16600) + ## [0.4.29](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.28...v0.4.29) * Fixed problem with evaluating "%" diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index bc036b8..193ec8d 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -66,8 +66,9 @@ def options end def unescape_incoming(str) - str.gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n"). - gsub(/\\\\/, '\\') + str.gsub(/((?:^|[^\\])(?:\\\\)*)((?:\\n)+)/) do |_| + $1 + "\n" * ($2.size / 2) + end.gsub(/\\\\/, '\\') end end diff --git a/test/ruby-debug/unescape_incoming_test.rb b/test/ruby-debug/unescape_incoming_test.rb index 0ac9488..6b8ecfa 100644 --- a/test/ruby-debug/unescape_incoming_test.rb +++ b/test/ruby-debug/unescape_incoming_test.rb @@ -28,6 +28,10 @@ def test_something do_test('"\\\\\\n".size', "\"\\\n\".size") end + def test_two_newlines + do_test('hello\n\nworld', "hello\n\nworld") + end + def do_test(input, expected_result) assert_equal(expected_result, Debugger::Command.unescape_incoming(input)) end From 4ef04c4e965190fe98b7a2832c4f64591abc53f8 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Apr 2015 14:54:16 +0300 Subject: [PATCH 123/302] It looks like String#inspect for var's representation creates more problem than fixes --- ChangeLog.md | 4 ++++ lib/ruby-debug-ide/xml_printer.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index b30feb0..9520cac 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,9 @@ ## [0.4.30](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.29...v0.4.30) +* reverting fix for + [RUBY-16192](https://youtrack.jetbrains.com/issue/RUBY-16192) to resolve + [RUBY-16435](https://youtrack.jetbrains.com/issue/RUBY-16435) + * unescaping of empty line fixed [RUBY-16600](https://youtrack.jetbrains.com/issue/RUBY-16600) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 6d4699d..88a95c7 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -154,7 +154,7 @@ def print_variable(name, value, kind) end elsif value.is_a?(String) has_children = value.respond_to?('bytes') || value.respond_to?('encoding') - value_str = value.inspect[1..-2] + value_str = value else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" From ca8e488d1ee8d26e7ca776d3acbe09a737f4f11e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 14 May 2015 14:29:49 +0300 Subject: [PATCH 124/302] Need to be prepared for exceptions in #print_variable E.g. such exception may occur for mock objects --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/version.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 9520cac..c9ff64e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.31](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.30...v0.4.31) + +* need to handle mock objects somehow + [RUBY-16665](https://youtrack.jetbrains.com/issue/RUBY-16665) + ## [0.4.30](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.29...v0.4.30) * reverting fix for diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 2e94623..11b4086 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.30' + IDE_VERSION='0.4.31' end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 88a95c7..63fcc32 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -178,6 +178,10 @@ def print_variable(name, value, kind) has_children, value.respond_to?(:object_id) ? value.object_id : value.id) print("", escaped_value_str) if Debugger.rm_protocol_extensions print('') + rescue StandardError => e + print_debug "Unexpected exception \"%s\"\n%s", e.to_s, e.backtrace.join("\n") + print("", + CGI.escapeHTML(name), kind, CGI.escapeHTML(value.to_s)) end def print_breakpoints(breakpoints) From ec89829e9469c18aba1ca85b87018b68a661d882 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 22 May 2015 12:21:32 +0300 Subject: [PATCH 125/302] Don't need yaml anymore (https://youtrack.jetbrains.com/issue/RUBY-16721) --- lib/ruby-debug-ide/xml_printer.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 63fcc32..281ab19 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -1,5 +1,4 @@ require 'cgi' -require 'yaml' require 'monitor' module Debugger @@ -332,7 +331,6 @@ def print(*params) end def handle_binary_data(value) - # noinspection RubyResolve return '[Binary Data]' if (value.respond_to?('is_binary_data?') && value.is_binary_data?) return '[Invalid encoding]' if (value.respond_to?('valid_encoding?') && !value.valid_encoding?) value From 2b36de1b261cac49c731e5a93ba274943defeada Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 22 May 2015 12:23:32 +0300 Subject: [PATCH 126/302] Version bumped up to 0.4.32 --- ChangeLog.md | 5 +++++ lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index c9ff64e..6384a70 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.32](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.31...v0.4.32) + +* Fixed problem with preloading psych + [RUBY-16721](https://youtrack.jetbrains.com/issue/RUBY-16721) + ## [0.4.31](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.30...v0.4.31) * need to handle mock objects somehow diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 11b4086..edb3581 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.31' + IDE_VERSION='0.4.32' end From 8ffcfe98fb5a3f90ef16d8dca7fb8740bf16b50b Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 22 Jul 2015 16:48:24 +0300 Subject: [PATCH 127/302] RUBY-16838: "smart" way to get string representation of JBuilder. Jbuilder.to_s returns nil instead of any reasonable string representation, to workaround it we use StringIO to get real representation. --- lib/ruby-debug-ide/xml_printer.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 281ab19..4c3e427 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -1,3 +1,4 @@ +require 'stringio' require 'cgi' require 'monitor' @@ -180,7 +181,7 @@ def print_variable(name, value, kind) rescue StandardError => e print_debug "Unexpected exception \"%s\"\n%s", e.to_s, e.backtrace.join("\n") print("", - CGI.escapeHTML(name), kind, CGI.escapeHTML(value.to_s)) + CGI.escapeHTML(name), kind, CGI.escapeHTML(safe_to_string(value))) end def print_breakpoints(breakpoints) @@ -379,6 +380,15 @@ def build_compact_value_attr(value, value_str) compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\"" end + def safe_to_string(value) + str = value.to_s + return str unless str.nil? + + string_io = StringIO.new + string_io.write(value) + string_io.string + end + def build_value_attr(escaped_value_str) Debugger.rm_protocol_extensions ? '' : "value=\"#{escaped_value_str}\"" end From a91f2921d12ff16459cc7691b93a5a82e4b672ef Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 22 Jul 2015 16:48:43 +0300 Subject: [PATCH 128/302] time to release 0.4.33 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index edb3581..ecaf8bd 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.32' + IDE_VERSION='0.4.33' end From 8df01d2b2dc19c62fe408b9cf78b8a391bd71c46 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 22 Jul 2015 16:49:01 +0300 Subject: [PATCH 129/302] time to release 0.4.33 --- ChangeLog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 6384a70..92312db 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,8 @@ +## [0.4.33](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.32...v0.4.33) + +* Fixed problem with inspecting Jbuilder + [RUBY-16838](https://youtrack.jetbrains.com/issue/RUBY-16838) + ## [0.4.32](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.31...v0.4.32) * Fixed problem with preloading psych From a39524789137ad3c5c4adeebadc80fdf2da1ea30 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:07:52 +0300 Subject: [PATCH 130/302] catchpointDeleted event added --- ChangeLog.md | 4 ++++ lib/ruby-debug-ide/commands/catchpoint.rb | 9 +++++++-- lib/ruby-debug-ide/version.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 4 ++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 92312db..1402ee2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +## [0.4.34](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.33...v0.4.34) + +* catchpointDeleted event added (under rm-protocol-extensions flag) + ## [0.4.33](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.32...v0.4.33) * Fixed problem with inspecting Jbuilder diff --git a/lib/ruby-debug-ide/commands/catchpoint.rb b/lib/ruby-debug-ide/commands/catchpoint.rb index 5aa4e29..9ed6b26 100644 --- a/lib/ruby-debug-ide/commands/catchpoint.rb +++ b/lib/ruby-debug-ide/commands/catchpoint.rb @@ -25,8 +25,11 @@ def execute errmsg "Off expected. Got %s\n", @match[2] elsif Debugger.catchpoints.member?(excn) Debugger.catchpoints.delete(excn) - print_catchpoint_set(excn) - #print "Catch for exception %s removed.\n", excn + if Debugger.rm_protocol_extensions + print_catchpoint_deleted(excn) + else + print_catchpoint_set(excn) + end else errmsg "Catch for exception %s not found.\n", excn end @@ -40,7 +43,9 @@ def help_command def help(cmd) %{ cat[ch]\t\t\tshow catchpoint + cat[ch] off \tremove all catch points cat[ch] \tset catchpoint to an exception + cat[ch] off \tremove catchpoint for an exception } end end diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index ecaf8bd..6240462 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.33' + IDE_VERSION='0.4.34' end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 4c3e427..b2373c1 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -216,6 +216,10 @@ def print_catchpoint_set(exception_class_name) print "", exception_class_name end + def print_catchpoint_deleted(exception_class_name) + print "", exception_class_name + end + def print_expressions(exps) print_element "expressions" do exps.each_with_index do |(exp, value), idx| From f2e1b5c81eb57190a83c922216e01e7724e912f6 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:10:01 +0300 Subject: [PATCH 131/302] Only XmlPrinter should know about protocol extensions --- lib/ruby-debug-ide/commands/catchpoint.rb | 6 +----- lib/ruby-debug-ide/xml_printer.rb | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ruby-debug-ide/commands/catchpoint.rb b/lib/ruby-debug-ide/commands/catchpoint.rb index 9ed6b26..f6e9592 100644 --- a/lib/ruby-debug-ide/commands/catchpoint.rb +++ b/lib/ruby-debug-ide/commands/catchpoint.rb @@ -25,11 +25,7 @@ def execute errmsg "Off expected. Got %s\n", @match[2] elsif Debugger.catchpoints.member?(excn) Debugger.catchpoints.delete(excn) - if Debugger.rm_protocol_extensions - print_catchpoint_deleted(excn) - else - print_catchpoint_set(excn) - end + print_catchpoint_deleted(excn) else errmsg "Catch for exception %s not found.\n", excn end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index b2373c1..f217994 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -217,7 +217,11 @@ def print_catchpoint_set(exception_class_name) end def print_catchpoint_deleted(exception_class_name) - print "", exception_class_name + if Debugger.rm_protocol_extensions + print "", exception_class_name + else + print_catchpoint_set(exception_class_name) + end end def print_expressions(exps) From 04093b0cf1f7618ab8d53055a62d8a466731adf1 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:15:01 +0300 Subject: [PATCH 132/302] Dedicated cli flag to enable catchpointDeleted event --- bin/rdebug-ide | 9 +++++++-- lib/ruby-debug-ide.rb | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 9361b7b..48b9804 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -20,7 +20,8 @@ options = OpenStruct.new( 'int_handler' => true, 'dispatcher_port' => -1, 'evaluation_timeout' => 10, - 'rm_protocol_extensions' => false + 'rm_protocol_extensions' => false, + 'catchpoint_deleted_event' => false ) opts = OptionParser.new do |opts| @@ -55,9 +56,12 @@ EOB opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true} opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false} - opts.on("--rubymine-protocol-extensions", "Enable RubyMine-specific incompatible protocol extensions") do + opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do options.rm_protocol_extensions = true end + opts.on("--catchpoint-deleted-event", "Enable chatchpointDeleted event") do + options.catchpoint_deleted_event = true + end opts.separator "" opts.separator "Common options:" opts.on_tail("-v", "--version", "Show version") do @@ -117,6 +121,7 @@ Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing Debugger.evaluation_timeout = options.evaluation_timeout Debugger.rm_protocol_extensions = options.rm_protocol_extensions +Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.debug_program(options) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 0135bff..769a626 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -44,6 +44,8 @@ def cleanup_backtrace(backtrace) attr_accessor :cli_debug, :xml_debug, :evaluation_timeout, :rm_protocol_extensions attr_accessor :control_thread attr_reader :interface + # protocol extensions + attr_accessor :catchpoint_deleted_event # From 2499b4a17ab0b00a6fb84996849476a5a556259f Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:15:36 +0300 Subject: [PATCH 133/302] Dedicated cli flag to enable catchpointDeleted event --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index f217994..6cc749f 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -217,7 +217,7 @@ def print_catchpoint_set(exception_class_name) end def print_catchpoint_deleted(exception_class_name) - if Debugger.rm_protocol_extensions + if Debugger.catchpoint_deleted_event print "", exception_class_name else print_catchpoint_set(exception_class_name) From beea10b9fcfa75d8fce1c3d27b3e0c25bf79fa89 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:19:43 +0300 Subject: [PATCH 134/302] --skip-value-attr so it is possible to enable this extension alone --- bin/rdebug-ide | 7 ++++++- lib/ruby-debug-ide.rb | 2 +- lib/ruby-debug-ide/xml_printer.rb | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 48b9804..1a2aaa9 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -21,7 +21,8 @@ options = OpenStruct.new( 'dispatcher_port' => -1, 'evaluation_timeout' => 10, 'rm_protocol_extensions' => false, - 'catchpoint_deleted_event' => false + 'catchpoint_deleted_event' => false, + 'skip_value_attr' => false ) opts = OptionParser.new do |opts| @@ -62,6 +63,9 @@ EOB opts.on("--catchpoint-deleted-event", "Enable chatchpointDeleted event") do options.catchpoint_deleted_event = true end + opts.on("--skip-value-attr", "Allow to skip value attribute in variable representation") do + options.skip_value_attr = true + end opts.separator "" opts.separator "Common options:" opts.on_tail("-v", "--version", "Show version") do @@ -122,6 +126,7 @@ Debugger.tracing = options.tracing Debugger.evaluation_timeout = options.evaluation_timeout Debugger.rm_protocol_extensions = options.rm_protocol_extensions Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions +Debugger.skip_value_attr = options.skip_value_attr || options.rm_protocol_extensions Debugger.debug_program(options) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 769a626..fef6eeb 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -45,7 +45,7 @@ def cleanup_backtrace(backtrace) attr_accessor :control_thread attr_reader :interface # protocol extensions - attr_accessor :catchpoint_deleted_event + attr_accessor :catchpoint_deleted_event, :skip_value_attr # diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 6cc749f..f56542c 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -398,7 +398,7 @@ def safe_to_string(value) end def build_value_attr(escaped_value_str) - Debugger.rm_protocol_extensions ? '' : "value=\"#{escaped_value_str}\"" + Debugger.skip_value_attr ? '' : "value=\"#{escaped_value_str}\"" end instance_methods.each do |m| From afeeb3a5717cc90631ad291a1295b6eb9ef0d11e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:27:25 +0300 Subject: [PATCH 135/302] better name for option --- ChangeLog.md | 3 ++- bin/rdebug-ide | 9 ++++----- lib/ruby-debug-ide.rb | 4 ++-- lib/ruby-debug-ide/xml_printer.rb | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 1402ee2..7dad6c2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,7 @@ ## [0.4.34](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.33...v0.4.34) -* catchpointDeleted event added (under rm-protocol-extensions flag) +* catchpointDeleted event added (under --catchpoint-deleted-event flag) +* --value-as-nested-element to enable just this the extension ## [0.4.33](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.32...v0.4.33) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 1a2aaa9..574dc44 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -22,7 +22,7 @@ options = OpenStruct.new( 'evaluation_timeout' => 10, 'rm_protocol_extensions' => false, 'catchpoint_deleted_event' => false, - 'skip_value_attr' => false + 'value_as_nested_element' => false ) opts = OptionParser.new do |opts| @@ -63,8 +63,8 @@ EOB opts.on("--catchpoint-deleted-event", "Enable chatchpointDeleted event") do options.catchpoint_deleted_event = true end - opts.on("--skip-value-attr", "Allow to skip value attribute in variable representation") do - options.skip_value_attr = true + opts.on("--value-as-nested-element", "Allow to pass variable's value as nested element instead of attribute") do + options.value_as_nested_element = true end opts.separator "" opts.separator "Common options:" @@ -124,9 +124,8 @@ end Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing Debugger.evaluation_timeout = options.evaluation_timeout -Debugger.rm_protocol_extensions = options.rm_protocol_extensions Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions -Debugger.skip_value_attr = options.skip_value_attr || options.rm_protocol_extensions +Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions Debugger.debug_program(options) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index fef6eeb..457f1a2 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -41,11 +41,11 @@ def cleanup_backtrace(backtrace) cleared end - attr_accessor :cli_debug, :xml_debug, :evaluation_timeout, :rm_protocol_extensions + attr_accessor :cli_debug, :xml_debug, :evaluation_timeout attr_accessor :control_thread attr_reader :interface # protocol extensions - attr_accessor :catchpoint_deleted_event, :skip_value_attr + attr_accessor :catchpoint_deleted_event, :value_as_nested_element # diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index f56542c..a50d5b1 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -176,7 +176,7 @@ def print_variable(name, value, kind) CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, build_value_attr(escaped_value_str), value.class, has_children, value.respond_to?(:object_id) ? value.object_id : value.id) - print("", escaped_value_str) if Debugger.rm_protocol_extensions + print("", escaped_value_str) if Debugger.value_as_nested_element print('') rescue StandardError => e print_debug "Unexpected exception \"%s\"\n%s", e.to_s, e.backtrace.join("\n") @@ -398,7 +398,7 @@ def safe_to_string(value) end def build_value_attr(escaped_value_str) - Debugger.skip_value_attr ? '' : "value=\"#{escaped_value_str}\"" + Debugger.value_as_nested_element ? '' : "value=\"#{escaped_value_str}\"" end instance_methods.each do |m| From a6cb91c43b28da089851ab98d5007e3bb28e9392 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:28:06 +0300 Subject: [PATCH 136/302] version bumped to 0.5.0 --- ChangeLog.md | 2 +- lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 7dad6c2..30ad34a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,4 @@ -## [0.4.34](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.33...v0.4.34) +## [0.5.0](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.33...v0.5.0) * catchpointDeleted event added (under --catchpoint-deleted-event flag) * --value-as-nested-element to enable just this the extension diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 6240462..89255ef 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.4.34' + IDE_VERSION='0.5.0' end From e43d605ae8b38f3c6f4e9adf684ba5bc80eb1204 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 24 Jul 2015 23:39:37 +0300 Subject: [PATCH 137/302] Create README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9e4024d --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +[gem]: https://rubygems.org/gems/ruby-debug-ide +# ruby-debug-ide +An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine. + +[![Gem Version](https://badge.fury.io/rb/ruby-debug-ide.svg)][gem] From bf0ce277f4051911222d3e794208b18bff34f1ec Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Jul 2015 16:17:17 +0300 Subject: [PATCH 138/302] version bumped to 0.6.0.pre1 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 89255ef..c7ab35d 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.5.0' + IDE_VERSION='0.6.0.pre1' end From 5d9a1f26ece300498c3047e65db0222bca0ad79c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Jul 2015 16:19:21 +0300 Subject: [PATCH 139/302] Let's print if file filtering is support on debugger's start --- lib/ruby-debug-ide.rb | 22 +++++++++++++++++++--- lib/ruby-debug-ide/command.rb | 17 ++++++++++++++++- lib/ruby-debug-ide/commands/breakpoints.rb | 11 ----------- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 457f1a2..994a49f 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -108,9 +108,7 @@ def start_control(host, port, notify_dispatcher) # "localhost" and nil have problems on some systems. host ||= '127.0.0.1' server = TCPServer.new(host, port) - gem_name = (defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0') ? 'ruby-debug-base' : - RUBY_VERSION < '2.0.0' ? 'ruby-debug-base19x' : 'debase' - $stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{gem_name} #{VERSION}) listens on #{host}:#{port}\n" + print_greeting_msg(host, port) notify_dispatcher(port) if notify_dispatcher while (session = server.accept) @@ -138,8 +136,26 @@ def start_control(host, port, notify_dispatcher) end end + def print_greeting_msg(host, port) + base_gem_name = if defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0' + 'ruby-debug-base' + elsif RUBY_VERSION < '2.0.0' + 'ruby-debug-base19x' + else + 'debase' + end + + file_filtering_support = if Command.file_fiter_supported? + 'supported' + else + 'not supported' + end + $stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{base_gem_name} #{VERSION}, file filtering is #{file_filtering_support}) listens on #{host}:#{port}\n" + end + private + def notify_dispatcher(port) return unless ENV['IDE_PROCESS_DISPATCHER'] acceptor_host, acceptor_port = ENV['IDE_PROCESS_DISPATCHER'].split(":") diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 193ec8d..1435062 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -70,6 +70,10 @@ def unescape_incoming(str) $1 + "\n" * ($2.size / 2) end.gsub(/\\\\/, '\\') end + + def file_fiter_supported? + defined?(Debugger.file_filter) + end end def initialize(state, printer) @@ -145,7 +149,18 @@ def line_at(file, line) def get_context(thnum) Debugger.contexts.find{|c| c.thnum == thnum} - end + end + + def realpath(filename) + if filename.index(File::SEPARATOR) || File::ALT_SEPARATOR && filename.index(File::ALT_SEPARATOR) + filename = File.expand_path(filename) + end + if (RUBY_VERSION < '1.9') || (RbConfig::CONFIG['host_os'] =~ /mswin/) + filename + else + File.realpath(filename) rescue filename + end + end end Command.load_commands diff --git a/lib/ruby-debug-ide/commands/breakpoints.rb b/lib/ruby-debug-ide/commands/breakpoints.rb index fb9fa6f..7a4f790 100644 --- a/lib/ruby-debug-ide/commands/breakpoints.rb +++ b/lib/ruby-debug-ide/commands/breakpoints.rb @@ -62,17 +62,6 @@ def help(cmd) } end end - - private - def realpath(filename) - filename = File.expand_path(filename) if filename.index(File::SEPARATOR) || \ - File::ALT_SEPARATOR && filename.index(File::ALT_SEPARATOR) - if (RUBY_VERSION < '1.9') || (RbConfig::CONFIG['host_os'] =~ /mswin/) - filename - else - File.realpath(filename) rescue filename - end - end end class BreakpointsCommand < Command # :nodoc: From 9cbd7d219428e08eefd65db2dea3d2cada7c1abf Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Jul 2015 16:23:42 +0300 Subject: [PATCH 140/302] "include " command added --- lib/ruby-debug-ide/commands/file_filtering.rb | 35 +++++++++++++++++++ lib/ruby-debug-ide/xml_printer.rb | 4 +++ 2 files changed, 39 insertions(+) create mode 100644 lib/ruby-debug-ide/commands/file_filtering.rb diff --git a/lib/ruby-debug-ide/commands/file_filtering.rb b/lib/ruby-debug-ide/commands/file_filtering.rb new file mode 100644 index 0000000..1561bdd --- /dev/null +++ b/lib/ruby-debug-ide/commands/file_filtering.rb @@ -0,0 +1,35 @@ +module Debugger + class IncludeDir < Command # :nodoc: + self.control = true + + def regexp + / ^\s*include\s+(.+?)\s*$/x + end + + def execute + file = @match[1] + + return if file.nil? + file = realpath(file) + + if Command.file_fiter_supported? + Debugger.file_filter.add(file) + print_dir_included(file) + else + print_debug("file filter is not supported") + end + end + + class << self + def help_command + 'include' + end + + def help(cmd) + %{ + file-filter include file - adds dir to list of included dirs + } + end + end + end +end \ No newline at end of file diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index a50d5b1..55b4a3a 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -184,6 +184,10 @@ def print_variable(name, value, kind) CGI.escapeHTML(name), kind, CGI.escapeHTML(safe_to_string(value))) end + def print_dir_included(file) + print("", file) + end + def print_breakpoints(breakpoints) print_element 'breakpoints' do breakpoints.sort_by{|b| b.id }.each do |b| From 4611e3a7ee6433916f4d9aedcbdb9fb413ec78dc Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 28 Jul 2015 16:30:13 +0300 Subject: [PATCH 141/302] "exclude " command added --- lib/ruby-debug-ide/commands/file_filtering.rb | 40 +++++++++++++++++-- lib/ruby-debug-ide/xml_printer.rb | 6 ++- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/commands/file_filtering.rb b/lib/ruby-debug-ide/commands/file_filtering.rb index 1561bdd..cb14090 100644 --- a/lib/ruby-debug-ide/commands/file_filtering.rb +++ b/lib/ruby-debug-ide/commands/file_filtering.rb @@ -13,8 +13,8 @@ def execute file = realpath(file) if Command.file_fiter_supported? - Debugger.file_filter.add(file) - print_dir_included(file) + Debugger.file_filter.include(file) + print_file_included(file) else print_debug("file filter is not supported") end @@ -27,7 +27,41 @@ def help_command def help(cmd) %{ - file-filter include file - adds dir to list of included dirs + include file - adds file/dir to file filter (either remove already excluded or add as included) + } + end + end + end + + class ExcludeFile < Command # :nodoc: + self.control = true + + def regexp + / ^\s*exclude\s+(.+?)\s*$/x + end + + def execute + file = @match[1] + + return if file.nil? + file = realpath(file) + + if Command.file_fiter_supported? + Debugger.file_filter.exclude(file) + print_file_excluded(file) + else + print_debug("file filter is not supported") + end + end + + class << self + def help_command + 'include' + end + + def help(cmd) + %{ + exclude file - exclude file/dir from file filter (either remove already included or add as exclude) } end end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 55b4a3a..5567769 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -184,10 +184,14 @@ def print_variable(name, value, kind) CGI.escapeHTML(name), kind, CGI.escapeHTML(safe_to_string(value))) end - def print_dir_included(file) + def print_file_included(file) print("", file) end + def print_file_excluded(file) + print("", file) + end + def print_breakpoints(breakpoints) print_element 'breakpoints' do breakpoints.sort_by{|b| b.id }.each do |b| From f39f9919da6a47547cfc6f6624c0f7b2d3470f24 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 29 Jul 2015 15:24:58 +0300 Subject: [PATCH 142/302] typo fixed --- lib/ruby-debug-ide.rb | 2 +- lib/ruby-debug-ide/command.rb | 2 +- lib/ruby-debug-ide/commands/file_filtering.rb | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 994a49f..9704f94 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -145,7 +145,7 @@ def print_greeting_msg(host, port) 'debase' end - file_filtering_support = if Command.file_fiter_supported? + file_filtering_support = if Command.file_filter_supported? 'supported' else 'not supported' diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 1435062..63f7ec0 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -71,7 +71,7 @@ def unescape_incoming(str) end.gsub(/\\\\/, '\\') end - def file_fiter_supported? + def file_filter_supported? defined?(Debugger.file_filter) end end diff --git a/lib/ruby-debug-ide/commands/file_filtering.rb b/lib/ruby-debug-ide/commands/file_filtering.rb index cb14090..0299e7d 100644 --- a/lib/ruby-debug-ide/commands/file_filtering.rb +++ b/lib/ruby-debug-ide/commands/file_filtering.rb @@ -12,7 +12,7 @@ def execute return if file.nil? file = realpath(file) - if Command.file_fiter_supported? + if Command.file_filter_supported? Debugger.file_filter.include(file) print_file_included(file) else @@ -46,7 +46,7 @@ def execute return if file.nil? file = realpath(file) - if Command.file_fiter_supported? + if Command.file_filter_supported? Debugger.file_filter.exclude(file) print_file_excluded(file) else From 47e01e21ab8048d76bc49826b4ac15a300d86a8e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 29 Jul 2015 15:48:46 +0300 Subject: [PATCH 143/302] "better" class name --- lib/ruby-debug-ide/commands/file_filtering.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/commands/file_filtering.rb b/lib/ruby-debug-ide/commands/file_filtering.rb index 0299e7d..55e92bb 100644 --- a/lib/ruby-debug-ide/commands/file_filtering.rb +++ b/lib/ruby-debug-ide/commands/file_filtering.rb @@ -1,5 +1,5 @@ module Debugger - class IncludeDir < Command # :nodoc: + class IncludeFile < Command # :nodoc: self.control = true def regexp From 5e3b6684bf80da086740ba8d97ca95f1c02e9553 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 29 Jul 2015 16:20:51 +0300 Subject: [PATCH 144/302] "file-filter on|off" command added --- lib/ruby-debug-ide/commands/file_filtering.rb | 38 +++++++++++++++++++ lib/ruby-debug-ide/xml_printer.rb | 4 ++ 2 files changed, 42 insertions(+) diff --git a/lib/ruby-debug-ide/commands/file_filtering.rb b/lib/ruby-debug-ide/commands/file_filtering.rb index 55e92bb..626d39d 100644 --- a/lib/ruby-debug-ide/commands/file_filtering.rb +++ b/lib/ruby-debug-ide/commands/file_filtering.rb @@ -66,4 +66,42 @@ def help(cmd) end end end + + class FileFilterCommand < Command # :nodoc: + self.control = true + + def regexp + / ^\s*file-filter\s+(on|off)\s*$/x + end + + def execute + action = @match[1] + + if Command.file_filter_supported? + if 'on' == action + Debugger.file_filter.enable + print_file_filter_status(true) + elsif 'off' == action + Debugger.file_filter.disable + print_file_filter_status(false) + else + print_error "Unknown option '#{action}'" + end + else + print_debug("file filter is not supported") + end + end + + class << self + def help_command + 'file-filter' + end + + def help(cmd) + %{ + file-filter (on|off) - enable/disable file filtering + } + end + end + end end \ No newline at end of file diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 5567769..3ef5140 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -192,6 +192,10 @@ def print_file_excluded(file) print("", file) end + def print_file_filter_status(status) + print("", status) + end + def print_breakpoints(breakpoints) print_element 'breakpoints' do breakpoints.sort_by{|b| b.id }.each do |b| From 0d7078d7907d8a3db405091463e0d8c42b8b0f82 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 29 Jul 2015 16:23:41 +0300 Subject: [PATCH 145/302] Changelog updated --- ChangeLog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 30ad34a..a739807 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,9 @@ +## [master](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.5.0...master) + +* "file-filter on|off" command added +* "include file|dir" command added +* "exclude file|dir" command added + ## [0.5.0](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.4.33...v0.5.0) * catchpointDeleted event added (under --catchpoint-deleted-event flag) From 64cbfcd16a80a4ebeeefa7f1bcd40adce751f9db Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 4 Aug 2015 15:39:09 +0300 Subject: [PATCH 146/302] Command.realpath should preserve / at the end of dir name --- lib/ruby-debug-ide/command.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 63f7ec0..1839af2 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -152,13 +152,16 @@ def get_context(thnum) end def realpath(filename) + is_dir = filename.end_with?(File::SEPARATOR) if filename.index(File::SEPARATOR) || File::ALT_SEPARATOR && filename.index(File::ALT_SEPARATOR) filename = File.expand_path(filename) end if (RUBY_VERSION < '1.9') || (RbConfig::CONFIG['host_os'] =~ /mswin/) filename else - File.realpath(filename) rescue filename + filename = File.realpath(filename) rescue filename + filename = filename + File::SEPARATOR if is_dir && !filename.end_with?(File::SEPARATOR) + filename end end end From c0cbccb0bcc326b30abface1390b1ee27c14c5e4 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 6 Aug 2015 13:39:40 +0300 Subject: [PATCH 147/302] version bumped up --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index c7ab35d..bbb2304 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.0.pre1' + IDE_VERSION='0.6.0.beta1' end From 4500ec556d1dda4abb7e6751b7fc44c28b057aea Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Tue, 18 Aug 2015 14:38:00 +0300 Subject: [PATCH 148/302] version bumped up to 0.6.0 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index bbb2304..b8e0c25 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.0.beta1' + IDE_VERSION='0.6.0' end From 0208503e9fa298e2da9fc5f0d92db7d82e155d2c Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 31 Aug 2015 15:45:19 +0300 Subject: [PATCH 149/302] Changelog updated for 0.6.0 --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index a739807..f96699b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,4 @@ -## [master](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.5.0...master) +## [0.6.0](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.5.0...0.6.0) * "file-filter on|off" command added * "include file|dir" command added From 62c83c8633d2569feb969f7ebf606f92e6889377 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 31 Aug 2015 15:48:04 +0300 Subject: [PATCH 150/302] Let's use Debugger#remove_catchpoint and Debugger#clear_catchpoints if available These methods allow some optimisations in debugger's backend --- ChangeLog.md | 4 ++++ lib/ruby-debug-ide/commands/catchpoint.rb | 23 +++++++++++++++++++---- lib/ruby-debug-ide/version.rb | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f96699b..8593f56 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +## [master](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.6.0...master) + +* let's use Debugger#remove_catchpoint and Debugger#clear_catchpoints if available + ## [0.6.0](https://github.com/ruby-debug/ruby-debug-ide/compare/v0.5.0...0.6.0) * "file-filter on|off" command added diff --git a/lib/ruby-debug-ide/commands/catchpoint.rb b/lib/ruby-debug-ide/commands/catchpoint.rb index f6e9592..eac29d3 100644 --- a/lib/ruby-debug-ide/commands/catchpoint.rb +++ b/lib/ruby-debug-ide/commands/catchpoint.rb @@ -16,21 +16,20 @@ def execute elsif not @match[2] # One arg given. if 'off' == excn - Debugger.catchpoints.clear + clear_catchpoints else Debugger.add_catchpoint(excn) print_catchpoint_set(excn) end elsif @match[2] != 'off' errmsg "Off expected. Got %s\n", @match[2] - elsif Debugger.catchpoints.member?(excn) - Debugger.catchpoints.delete(excn) + elsif remove_catchpoint(excn) print_catchpoint_deleted(excn) else errmsg "Catch for exception %s not found.\n", excn end end - + class << self def help_command 'catch' @@ -45,5 +44,21 @@ def help(cmd) } end end + + private + + def clear_catchpoints + if Debugger.respond_to?(:clear_catchpoints) + Debugger.clear_catchpoints + else + Debugger.catchpoints.clear + end + end + + def remove_catchpoint(excn) + return Debugger.remove_catchpoint(excn) if Debugger.respond_to?(:remove_catchpoint) + return Debugger.catchpoints.delete(excn) if Debugger.catchpoints.member?(excn) + false + end end end diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index b8e0c25..1b8ca16 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.0' + IDE_VERSION='0.6.1.beta1' end From 17b9d602923fdce28f8fe600bddf56ba4760425c Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 8 Oct 2015 19:48:11 +0300 Subject: [PATCH 151/302] More path escaping to prevent faults on paths with ampersand --- lib/ruby-debug-ide/xml_printer.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 3ef5140..1e729d6 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -199,13 +199,13 @@ def print_file_filter_status(status) def print_breakpoints(breakpoints) print_element 'breakpoints' do breakpoints.sort_by{|b| b.id }.each do |b| - print "", b.id, b.source, b.pos.to_s + print "", b.id, CGI.escapeHTML(b.source), b.pos.to_s end end end def print_breakpoint_added(b) - print "", b.id, b.source, b.pos + print "", b.id, CGI.escapeHTML(b.source), b.pos end def print_breakpoint_deleted(b) @@ -289,14 +289,14 @@ def print_methods(methods) # Events def print_breakpoint(_, breakpoint) - print("", - breakpoint.source, breakpoint.pos, Debugger.current_context.thnum) + print("", + CGI.escapeHTML(breakpoint.source), breakpoint.pos, Debugger.current_context.thnum) end def print_catchpoint(exception) context = Debugger.current_context print("", - context.frame_file(0), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum) + CGI.escapeHTML(context.frame_file(0)), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum) end def print_trace(context, file, line) From ca281ed7bcf0fbfd1af39077fef46fb3c6e7f520 Mon Sep 17 00:00:00 2001 From: Robert Reiz Date: Thu, 5 Nov 2015 15:48:21 +0100 Subject: [PATCH 152/302] Adding MIT license to the gemspec. --- ruby-debug-ide.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/ruby-debug-ide.gemspec b/ruby-debug-ide.gemspec index 00d2e45..b448205 100644 --- a/ruby-debug-ide.gemspec +++ b/ruby-debug-ide.gemspec @@ -32,6 +32,7 @@ EOF spec.author = "Markus Barchfeld, Martin Krauskopf, Mark Moseley, JetBrains RubyMine Team" spec.email = "rubymine-feedback@jetbrains.com" + spec.license = "MIT" spec.platform = Gem::Platform::RUBY spec.require_path = "lib" spec.bindir = "bin" From 9fe6aa34012092372c413797e7082c41bde97a60 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 14 Mar 2016 20:01:36 +0300 Subject: [PATCH 153/302] don't break if object doesn't support to_s (e.g. BasicObject) --- lib/ruby-debug-ide/xml_printer.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 1e729d6..00f08b5 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -401,7 +401,11 @@ def build_compact_value_attr(value, value_str) end def safe_to_string(value) - str = value.to_s + begin + str = value.to_s + rescue NoMethodError + str = "(Object doesn't support #to_s)" + end return str unless str.nil? string_io = StringIO.new From ce3dbe0a76e11f34abf60740b7c88b23a1c3b5bf Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 21 Mar 2016 14:04:00 +0300 Subject: [PATCH 154/302] bump --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 1b8ca16..48c578c 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta1' + IDE_VERSION='0.6.1.beta2' end From 3681a0592cb8894f8c89b99c7a11bc4ca0729374 Mon Sep 17 00:00:00 2001 From: "dmitrii.kravchenko" Date: Mon, 8 Aug 2016 16:30:48 +0300 Subject: [PATCH 155/302] attach mode added --- bin/rdebug-ide | 28 ++++++++++++++------ lib/ruby-debug-ide.rb | 13 ++++----- lib/ruby-debug-ide/commands/control.rb | 27 +++++++++++++++++++ lib/ruby-debug-ide/ide_processor.rb | 5 ++-- lib/ruby-debug-ide/multiprocess/pre_child.rb | 8 +++--- 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 574dc44..d73b94d 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -22,7 +22,8 @@ options = OpenStruct.new( 'evaluation_timeout' => 10, 'rm_protocol_extensions' => false, 'catchpoint_deleted_event' => false, - 'value_as_nested_element' => false + 'value_as_nested_element' => false, + 'attach_mode' => false ) opts = OptionParser.new do |opts| @@ -54,7 +55,9 @@ EOB opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path| $LOAD_PATH.unshift(path) end - + opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do + options.attach_mode = true + end opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true} opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false} opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do @@ -89,15 +92,17 @@ rescue StandardError => e exit(1) end -if ARGV.empty? +if ARGV.empty? && !options.attach_mode puts opts puts puts "Must specify a script to run" exit(1) -end +end -# save script name -Debugger::PROG_SCRIPT = ARGV.shift +unless options.attach_mode + # save script name + Debugger::PROG_SCRIPT = ARGV.shift +end if options.dispatcher_port != -1 ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s @@ -119,7 +124,7 @@ if options.int_handler # install interruption handler trap('INT') { Debugger.interrupt_last } end - + # set options Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing @@ -127,5 +132,12 @@ Debugger.evaluation_timeout = options.evaluation_timeout Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions -Debugger.debug_program(options) +if options.attach_mode + Debugger::MultiProcess::pre_child(options) + if Debugger::FRONT_END == "debase" + Debugger.enable_trace_points + end +else + Debugger.debug_program(options) +end diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 9704f94..4e0552b 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -4,14 +4,16 @@ require 'thread' if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION) require 'ruby-debug-base' + Debugger::FRONT_END = "ruby-debug-base" else require 'debase' + Debugger::FRONT_END = "debase" end -require 'ruby-debug-ide/version' -require 'ruby-debug-ide/xml_printer' -require 'ruby-debug-ide/ide_processor' -require 'ruby-debug-ide/event_processor' +require_relative 'ruby-debug-ide/version' +require_relative 'ruby-debug-ide/xml_printer' +require_relative 'ruby-debug-ide/ide_processor' +require_relative 'ruby-debug-ide/event_processor' module Debugger @@ -110,7 +112,6 @@ def start_control(host, port, notify_dispatcher) server = TCPServer.new(host, port) print_greeting_msg(host, port) notify_dispatcher(port) if notify_dispatcher - while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug dispatcher = ENV['IDE_PROCESS_DISPATCHER'] @@ -160,8 +161,8 @@ def notify_dispatcher(port) return unless 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) diff --git a/lib/ruby-debug-ide/commands/control.rb b/lib/ruby-debug-ide/commands/control.rb index c8ff56f..0fffb4d8 100644 --- a/lib/ruby-debug-ide/commands/control.rb +++ b/lib/ruby-debug-ide/commands/control.rb @@ -126,4 +126,31 @@ def help(cmd) end end end + + + class DetachCommand < Command # :nodoc: + self.control = true + + def regexp + /^\s*detach\s*$/ + end + + def execute + Debugger.stop + Debugger.control_thread = nil + Thread.current.exit #@control_thread is a current thread + end + + class << self + def help_command + 'detach' + end + + def help(cmd) + %{ + detach\ndetach debugger\nnote: this option is only for remote debugging (or local attach) + } + end + end + end end diff --git a/lib/ruby-debug-ide/ide_processor.rb b/lib/ruby-debug-ide/ide_processor.rb index e5b7e98..ac07a0f 100644 --- a/lib/ruby-debug-ide/ide_processor.rb +++ b/lib/ruby-debug-ide/ide_processor.rb @@ -1,5 +1,5 @@ -require 'ruby-debug-ide/interface' -require 'ruby-debug-ide/command' +require_relative 'interface' +require_relative 'command' module Debugger class IdeCommandProcessor @@ -77,7 +77,6 @@ def process_commands ctrl_cmd_classes = Command.commands.select{|cmd| cmd.control} state = ControlState.new(@interface) ctrl_cmds = ctrl_cmd_classes.map{|cmd| cmd.new(state, @printer)} - while input = @interface.read_command # escape % since print_debug might use printf # sleep 0.3 diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 1b9c2cc..eb96242 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -1,19 +1,17 @@ module Debugger module MultiProcess class << self - def pre_child - + def pre_child(options = nil) require 'socket' require 'ostruct' host = ENV['DEBUGGER_HOST'] - port = find_free_port(host) - options = OpenStruct.new( + options ||= OpenStruct.new( 'frame_bind' => false, 'host' => host, 'load_mode' => false, - 'port' => port, + 'port' => find_free_port(host), 'stop' => false, 'tracing' => false, 'int_handler' => true, From 72b1c4af766f3926c9373a257efcb58bb65d27da Mon Sep 17 00:00:00 2001 From: "dmitrii.kravchenko" Date: Mon, 8 Aug 2016 16:59:19 +0300 Subject: [PATCH 156/302] gdb_wrapper and debugger_loader added --- bin/gdb_wrapper | 93 ++++++++++++++++++++ lib/ruby-debug-ide/attach/debugger_loader.rb | 20 +++++ 2 files changed, 113 insertions(+) create mode 100755 bin/gdb_wrapper create mode 100644 lib/ruby-debug-ide/attach/debugger_loader.rb diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper new file mode 100755 index 0000000..c56597d --- /dev/null +++ b/bin/gdb_wrapper @@ -0,0 +1,93 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'ostruct' + +options = OpenStruct.new( + 'pid' => nil, + 'sdk_path' => nil, + 'uid' => nil, + 'gems_to_include' => [] +) + +opts = OptionParser.new do |opts| + # TODO need some banner + opts.banner = < Date: Tue, 9 Aug 2016 14:16:01 +0300 Subject: [PATCH 157/302] closing interface --- lib/ruby-debug-ide/commands/control.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ruby-debug-ide/commands/control.rb b/lib/ruby-debug-ide/commands/control.rb index 0fffb4d8..f518c02 100644 --- a/lib/ruby-debug-ide/commands/control.rb +++ b/lib/ruby-debug-ide/commands/control.rb @@ -137,6 +137,7 @@ def regexp def execute Debugger.stop + Debugger.interface.close Debugger.control_thread = nil Thread.current.exit #@control_thread is a current thread end From fa128e1b496cfdd74f0cff78f773f5a3228dc56e Mon Sep 17 00:00:00 2001 From: "dmitrii.kravchenko" Date: Mon, 15 Aug 2016 16:00:15 +0300 Subject: [PATCH 158/302] relative imports replaced with normal ones. `print_greeting_msg` now in separate file. `enable_trace_points` call (wrong) replaced with empty_file loading (ugly but should always work). Including gems into $LOAD_PATH. --- bin/gdb_wrapper | 39 +++++++++++-------- bin/rdebug-ide | 11 ++++-- lib/ruby-debug-ide.rb | 25 ++---------- lib/ruby-debug-ide/attach/debugger_loader.rb | 6 +-- lib/ruby-debug-ide/attach/empty_file.rb | 0 lib/ruby-debug-ide/greeter.rb | 40 ++++++++++++++++++++ lib/ruby-debug-ide/ide_processor.rb | 4 +- ruby-debug-ide.gemspec | 2 +- 8 files changed, 81 insertions(+), 46 deletions(-) create mode 100644 lib/ruby-debug-ide/attach/empty_file.rb create mode 100644 lib/ruby-debug-ide/greeter.rb diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index c56597d..ba56a55 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -13,15 +13,15 @@ options = OpenStruct.new( opts = OptionParser.new do |opts| # TODO need some banner opts.banner = < Date: Wed, 31 Aug 2016 19:14:11 +0300 Subject: [PATCH 159/302] bug fix: cli_debug should be part of options because pre_child sets Debugger.cli_debug = options.cli_debug; bug fix: check RUBYOPT and $: if they already contain our paths (relevant in case of attaching several time to some process); bug fix: calling `prepare_context` instead of `enable_tracepoints`; calling `init_variables` to reset all debase variables from previous attaching --- bin/rdebug-ide | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 6ba9047..26295f3 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -23,7 +23,8 @@ options = OpenStruct.new( 'rm_protocol_extensions' => false, 'catchpoint_deleted_event' => false, 'value_as_nested_element' => false, - 'attach_mode' => false + 'attach_mode' => false, + 'cli_debug' => false ) opts = OptionParser.new do |opts| @@ -48,6 +49,7 @@ EOB opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true} opts.on("-d", "--debug", "Debug self - prints information for debugging ruby-debug itself") do Debugger.cli_debug = true + options.cli_debug = true end opts.on("--xml-debug", "Debug self - sends information s for debugging ruby-debug itself") do Debugger.xml_debug = true @@ -109,16 +111,20 @@ end if options.dispatcher_port != -1 ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s if RUBY_VERSION < "1.9" - $: << File.expand_path(File.dirname(__FILE__) + "/../lib/") + lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib/") + $: << lib_path unless $:.include? lib_path require 'ruby-debug-ide/multiprocess' else require_relative '../lib/ruby-debug-ide/multiprocess' end ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB'] - old_opts = ENV['RUBYOPT'] - ENV['RUBYOPT'] = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter" - ENV['RUBYOPT'] += " #{old_opts}" if old_opts + old_opts = ENV['RUBYOPT'] || '' + starter = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter" + unless old_opts.include? starter + ENV['RUBYOPT'] = starter + ENV['RUBYOPT'] += " #{old_opts}" if old_opts != '' + end ENV['DEBUGGER_CLI_DEBUG'] = Debugger.cli_debug.to_s end @@ -135,13 +141,15 @@ Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options. Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions if options.attach_mode + if Debugger::FRONT_END == "debase" + Debugger.init_variables + end + Debugger::MultiProcess::pre_child(options) - # This will trigger `setup_tracepoints` and `prepare_context` (which is private in debase) - # without any actual excessive code execution. if Debugger::FRONT_END == "debase" - EMPTY_TEMPLATE = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/empty_file.rb' - Debugger.debug_load(EMPTY_TEMPLATE) + Debugger.setup_tracepoints + Debugger.prepare_context end else Debugger.debug_program(options) From 0c2a3295c91306ca57acc7a39dfc2fefab06ffca Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Wed, 31 Aug 2016 21:45:46 +0300 Subject: [PATCH 160/302] added interaction with gdb, added c-level attaching --- bin/gdb_wrapper | 253 +++++++++++++++++++----- ext/Makefile | 10 + ext/do_attach.c | 37 ++++ ext/do_attach.h | 10 + lib/ruby-debug-ide/attach/empty_file.rb | 0 5 files changed, 266 insertions(+), 44 deletions(-) create mode 100644 ext/Makefile create mode 100644 ext/do_attach.c create mode 100644 ext/do_attach.h delete mode 100644 lib/ruby-debug-ide/attach/empty_file.rb diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index ba56a55..4562384 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -3,11 +3,14 @@ require 'optparse' require 'ostruct' +$stdout.sync = true +$stderr.sync = true + options = OpenStruct.new( - 'pid' => nil, - 'sdk_path' => nil, - 'uid' => nil, - 'gems_to_include' => [] + 'pid' => nil, + 'sdk_path' => nil, + 'uid' => nil, + 'gems_to_include' => [] ) opts = OptionParser.new do |opts| @@ -16,19 +19,19 @@ opts = OptionParser.new do |opts| Some useful banner. EOB - opts.on("--pid PID", "pid of process you want to attach to for debugging") do |pid| + opts.on('--pid PID', 'pid of process you want to attach to for debugging') do |pid| options.pid = pid end - opts.on("--ruby-path SDK_PATH", "path to ruby interpreter") do |ruby_path| + opts.on('--ruby-path RUBY_PATH', 'path to ruby interpreter') do |ruby_path| options.ruby_path = ruby_path end - opts.on("--uid UID", "uid which this process should set after executing gdb attach") do |uid| + opts.on('--uid UID', 'uid which this process should set after executing gdb attach') do |uid| options.uid = uid end - opts.on("--include-gem GEM_LIB_PATH", "lib of gem to include") do |gem_lib_path| + opts.on('--include-gem GEM_LIB_PATH', 'lib of gem to include') do |gem_lib_path| options.gems_to_include << gem_lib_path end end @@ -36,62 +39,224 @@ end opts.parse! ARGV unless options.pid - $stderr.puts "You must specify PID of process you want to attach to" + $stderr.puts 'You should specify PID of process you want to attach to' exit 1 end unless options.ruby_path - $stderr.puts "You must specify RUBY_PATH of ruby interpreter" + $stderr.puts 'You should specify path to the ruby interpreter' exit 1 end -# TODO Denis told not to implement this hack -# So this is only for me while debugging as -# I don't want to get any warnings. -sigints_caught = 0 -trap('INT') do - sigints_caught += 1 - if sigints_caught == 2 - exit 0 - end -end - argv = '["' + ARGV * '", "' + '"]' gems_to_include = '["' + options.gems_to_include * '", "' + '"]' -commands_list = [] +path_to_debugger_loader = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' -def commands_list.<<(command) - self.push "-ex \"#{command}\"" +options.gems_to_include.each do |gem_path| + $LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path) end -path_to_debugger_loader = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' +require 'ruby-debug-ide/greeter' +Debugger::print_greeting_msg(nil, nil) -# rb_finish: wait while execution comes to the next line. -# This is essential because we could interrupt process in a middle -# of some evaluations (e.g., system call) -commands_list << "call rb_eval_string_protect(\\\"set_trace_func lambda{|event, file, line, id, binding, classname| if /line/ =~ event; sleep 0; set_trace_func(nil); end}\\\", (int *)0)" -commands_list << "tbreak rb_f_sleep" -commands_list << "cont" +$pid = options.pid +$last_bt = '' +$gdb_tmp_file = '/tmp/gdb_out.txt' -# evalr: loading debugger into the process -evalr = "call rb_eval_string_protect(%s, (int *)0)" -commands_list << ("#{evalr}" % ["(\\\"require '#{path_to_debugger_loader}'; load_debugger(#{gems_to_include.gsub("\"", "'")}, #{argv.gsub("\"", "'")})\\\")"]) +begin + file = File.open($gdb_tmp_file, 'w') + file.truncate(0) + file.close +rescue Exception => e + $stderr.puts e + $stderr.puts "Could not create file #{$gdb_tmp_file} for gdb logging. Aborting." + exit! +end -# q: exit gdb and continue process execution with debugger -commands_list << "q" +gdb_executed_all_commands = false -cmd = "gdb #{options.ruby_path} #{options.pid} -nh -nx -batch #{commands_list.join(" ")}" +IO.popen("gdb #{options.ruby_path} #{options.pid} -nh -nx", 'r+') do |gdb| -options.gems_to_include.each do |gem_path| - $LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path) -end + $gdb = gdb + $main_thread = nil -require 'ruby-debug-ide/greeter' -Debugger::print_greeting_msg(nil, nil) -$stderr.puts "Running command #{cmd}" + class ProcessThread + + attr_reader :thread_num, :is_main + + def initialize(thread_num, is_main) + @thread_num = thread_num + @is_main = is_main + end + + def switch + $gdb.execute "thread #{thread_num}" + end + + def finish + $gdb.finish + end + + def get_bt + return $gdb.execute 'bt' + end + + def top_caller_match(bt, pattern) + return bt.split('#')[1] =~ /#{pattern}/ + end + + def any_caller_match(bt, pattern) + return bt =~ /#{pattern}/ + end + + def is_inside_malloc(bt = get_bt) + if any_caller_match(bt, '(malloc\.c)') + $stderr.puts "process #{$pid} is currently inside malloc." + return true + else + return false + end + end + + def is_inside_gc(bt = get_bt) + if any_caller_match(bt, '(gc\.c)') + $stderr.puts "process #{$pid} is currently in garbage collection phase." + return true + else + return false + end + end + + def need_finish_frame + bt = get_bt + return is_inside_malloc(bt) || is_inside_gc(bt) + end + + end + + def gdb.update_threads + process_threads = [] + info_threads = (self.execute 'info threads').split("\n") + # first line of gdb's response is ` Id Target Id Frame` info line + # last line of gdb's response is `(gdb) ` + info_threads.shift + info_threads.pop + # each thread info looks like this: + # 3 Thread 0x7ff535405700 (LWP 8291) "ruby-timer-thr" 0x00007ff534a15fdd in poll () at ../sysdeps/unix/syscall-template.S:81 + info_threads.each do |thread_info| + next unless thread_info =~ /[\s*]*\d+\s+Thread.*/ + $stderr.puts "thread_info: #{thread_info}" + is_main = thread_info[0] == '*' + thread_info.sub!(/[\s*]*/, '') + thread_info.sub!(/\s.*$/, '') + thread = ProcessThread.new(thread_info.to_i, is_main) + if thread.is_main + $main_thread = thread + end + process_threads << thread + end + process_threads + end + + def gdb.get_response + content = '' + loop do + sleep 0.01 # give time to gdb to finish command execution and print it to file + file = File.open($gdb_tmp_file, 'r') + content = file.read + file.close + break if content =~ /\(gdb\)\s\z/ + end + content + end + + def gdb.enable_logging + self.puts 'set logging on' + end + + def gdb.disable_logging + self.puts 'set logging off' + end + + def gdb.overwrite_file + disable_logging + enable_logging + end + + def gdb.execute(command) + self.overwrite_file + self.puts command + $stdout.puts "executed command '#{command}' inside gdb." + if command == 'q' + return '' + end + response = self.get_response + if command == 'bt' + $last_bt = response + end + return response + end + + def gdb.finish + $stdout.puts 'trying to finish current frame.' + self.execute 'finish' + end + + def gdb.set_logging + self.puts "set logging file #{$gdb_tmp_file}" + self.puts 'set logging overwrite on' + self.puts 'set logging redirect on' + self.enable_logging + + $stdout.puts "all gdb output redirected to #{$gdb_tmp_file}." + end + + def gdb.check_already_under_debug + threads = self.execute 'info threads' + return threads =~ /ruby-debug-ide/ + end -`#{cmd}` or raise "GDB failed. Aborting." + gdb.set_logging + + if gdb.check_already_under_debug + $stderr.puts "Process #{$pid} is already under debug" + gdb.execute 'q' + end + + gdb.execute 'set scheduler-locking off' + gdb.execute 'set unwindonsignal on' + + should_check_threads_state = true + + while should_check_threads_state + should_check_threads_state = false + gdb.update_threads.each do |thread| + thread.switch + while thread.need_finish_frame + should_check_threads_state = true + thread.finish + end + end + end + + $main_thread.switch + + gdb.execute "call dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" + gdb.execute "call start_attach(\"require '#{path_to_debugger_loader}'; load_debugger(#{gems_to_include.gsub("\"", "'")}, #{argv.gsub("\"", "'")})\")" + + gdb_executed_all_commands = true + gdb.execute 'q' + +end + +trap('INT') do + unless gdb_executed_all_commands + $stderr.puts "Seems like could not attach to process. Its backtrace:\n#{$last_bt}" + $stderr.flush + end + exit 1 +end if options.uid Process::Sys.setuid(options.uid.to_i) diff --git a/ext/Makefile b/ext/Makefile new file mode 100644 index 0000000..9bec56c --- /dev/null +++ b/ext/Makefile @@ -0,0 +1,10 @@ +all: libAttach.so + +libAttach.so: libAttach.o + gcc -shared -o libAttach.so libAttach.o + +libAttach.o: do_attach.c + gcc -Wall -g -fPIC -c -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0 -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0/x86_64-linux/ do_attach.c -o libAttach.o + +clean: + rm libAttach.* diff --git a/ext/do_attach.c b/ext/do_attach.c new file mode 100644 index 0000000..7291b48 --- /dev/null +++ b/ext/do_attach.c @@ -0,0 +1,37 @@ +#include "do_attach.h" + +static const char *_command_to_eval; + +static int +__check_gc(void) +{ + if (rb_during_gc()) { + fprintf(stderr, "Can not connect during garbage collection phase. Please, try again later.\n"); + return 1; + } + return 0; +} + +static void +__catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass) +{ + (void)sizeof(evflag); + (void)sizeof(self); + (void)sizeof(mid); + (void)sizeof(klass); + + rb_remove_event_hook(__catch_line_event); + if (__check_gc()) + return; + rb_eval_string_protect(_command_to_eval, NULL); // TODO pass something more useful than NULL +} + +void +start_attach(const char* command) +{ + _command_to_eval = command; + if (__check_gc()) + return; + rb_global_variable((VALUE *) _command_to_eval); + rb_add_event_hook(__catch_line_event, RUBY_EVENT_LINE, (VALUE) NULL); +} diff --git a/ext/do_attach.h b/ext/do_attach.h new file mode 100644 index 0000000..3697d3f --- /dev/null +++ b/ext/do_attach.h @@ -0,0 +1,10 @@ +#ifndef __DO_ATTACH_H__ +#define __DO_ATTACH_H__ + +#include +#include +#include + +void start_attach(const char *command); + +#endif //__DO_ATTACH_H__ \ No newline at end of file diff --git a/lib/ruby-debug-ide/attach/empty_file.rb b/lib/ruby-debug-ide/attach/empty_file.rb deleted file mode 100644 index e69de29..0000000 From 9c96a7689f8cc5249e3fad5cdd71470a550f914a Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Thu, 1 Sep 2016 14:20:56 +0300 Subject: [PATCH 161/302] added `attached` flag to indicate if we are currently under debug. This is needed for attach mode: if we detached `pre_child` should not be called in `fork` and `exec` --- bin/rdebug-ide | 2 ++ lib/ruby-debug-ide.rb | 1 + lib/ruby-debug-ide/commands/control.rb | 1 + lib/ruby-debug-ide/multiprocess/pre_child.rb | 2 ++ 4 files changed, 6 insertions(+) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 26295f3..dced3a7 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -140,6 +140,8 @@ Debugger.evaluation_timeout = options.evaluation_timeout Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions +Debugger.attached = true + if options.attach_mode if Debugger::FRONT_END == "debase" Debugger.init_variables diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index db12c79..30fc079 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -43,6 +43,7 @@ def cleanup_backtrace(backtrace) cleared end + attr_accessor :attached attr_accessor :cli_debug, :xml_debug, :evaluation_timeout attr_accessor :control_thread attr_reader :interface diff --git a/lib/ruby-debug-ide/commands/control.rb b/lib/ruby-debug-ide/commands/control.rb index f518c02..bc09bda 100644 --- a/lib/ruby-debug-ide/commands/control.rb +++ b/lib/ruby-debug-ide/commands/control.rb @@ -136,6 +136,7 @@ def regexp end def execute + Debugger.attached = false Debugger.stop Debugger.interface.close Debugger.control_thread = nil diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index eb96242..7a2f4fc 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -2,6 +2,8 @@ module Debugger module MultiProcess class << self def pre_child(options = nil) + return unless Debugger.attached + require 'socket' require 'ostruct' From 32f61feb231bf3953027bf2a0bd79add4b41af73 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Fri, 2 Sep 2016 21:19:26 +0300 Subject: [PATCH 162/302] lldb added --- bin/gdb_wrapper | 378 +++++++++++++++++++++++++++++------------------- ext/do_attach.c | 14 +- ext/do_attach.h | 2 +- 3 files changed, 244 insertions(+), 150 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 4562384..5482744 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -6,7 +6,7 @@ require 'ostruct' $stdout.sync = true $stderr.sync = true -options = OpenStruct.new( +@options = OpenStruct.new( 'pid' => nil, 'sdk_path' => nil, 'uid' => nil, @@ -20,246 +20,332 @@ Some useful banner. EOB opts.on('--pid PID', 'pid of process you want to attach to for debugging') do |pid| - options.pid = pid + @options.pid = pid end opts.on('--ruby-path RUBY_PATH', 'path to ruby interpreter') do |ruby_path| - options.ruby_path = ruby_path + @options.ruby_path = ruby_path end opts.on('--uid UID', 'uid which this process should set after executing gdb attach') do |uid| - options.uid = uid + @options.uid = uid end opts.on('--include-gem GEM_LIB_PATH', 'lib of gem to include') do |gem_lib_path| - options.gems_to_include << gem_lib_path + @options.gems_to_include << gem_lib_path end end opts.parse! ARGV -unless options.pid +unless @options.pid $stderr.puts 'You should specify PID of process you want to attach to' exit 1 end -unless options.ruby_path +unless @options.ruby_path $stderr.puts 'You should specify path to the ruby interpreter' exit 1 end -argv = '["' + ARGV * '", "' + '"]' -gems_to_include = '["' + options.gems_to_include * '", "' + '"]' +$argv = '["' + ARGV * '", "' + '"]' +$gems_to_include = '["' + @options.gems_to_include * '", "' + '"]' +$path_to_debugger_loader = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' -path_to_debugger_loader = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' - -options.gems_to_include.each do |gem_path| +@options.gems_to_include.each do |gem_path| $LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path) end require 'ruby-debug-ide/greeter' Debugger::print_greeting_msg(nil, nil) -$pid = options.pid -$last_bt = '' -$gdb_tmp_file = '/tmp/gdb_out.txt' - -begin - file = File.open($gdb_tmp_file, 'w') - file.truncate(0) - file.close -rescue Exception => e - $stderr.puts e - $stderr.puts "Could not create file #{$gdb_tmp_file} for gdb logging. Aborting." - exit! -end - -gdb_executed_all_commands = false +# this class is some kind of "interface" +class NativeDebugger -IO.popen("gdb #{options.ruby_path} #{options.pid} -nh -nx", 'r+') do |gdb| + attr_reader :pid, :last_bt - $gdb = gdb - $main_thread = nil + # @param executable -- path to ruby interpreter + # @param pid -- pid of process you want to debug + # @param options -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit) + def initialize(executable, pid, options) + @pid = pid + @main_thread = nil + @delimiter = '__OUTPUT_FINISHED__' # for getting response + @last_bt = '' # to shaw it to user - class ProcessThread + launch_string = "#{self} #{executable} #{options}" + @pipe = IO.popen(launch_string, 'r+') + $stdout.puts "executed '#{launch_string}'" + end - attr_reader :thread_num, :is_main + def attach_to_process + execute "attach #{@pid}" + end - def initialize(thread_num, is_main) - @thread_num = thread_num - @is_main = is_main + def execute(command) + @pipe.puts command + $stdout.puts "executed `#{command}` command inside #{self}." + if command == 'q' + @pipe.close + return '' end - - def switch - $gdb.execute "thread #{thread_num}" + response = get_response + if command == 'bt' + @last_bt = response end + $stdout.puts "response for #{command}:\n#{response}\n\n\n\n" + response + end - def finish - $gdb.finish - end + def get_response + # we need this hack to understand that debugger gave us all output from last executed command + @pipe.puts "print \"#{@delimiter}\"" - def get_bt - return $gdb.execute 'bt' + content = '' + loop do + line = @pipe.readline + $stderr.puts line + next if line =~ /\(lldb\)/ # lldb repeats your input to its output + break if line =~ /\$\d+\s=\s"__OUTPUT_FINISHED__"/ + content += line end + content + end - def top_caller_match(bt, pattern) - return bt.split('#')[1] =~ /#{pattern}/ - end + def update_threads - def any_caller_match(bt, pattern) - return bt =~ /#{pattern}/ - end + end - def is_inside_malloc(bt = get_bt) - if any_caller_match(bt, '(malloc\.c)') - $stderr.puts "process #{$pid} is currently inside malloc." - return true - else - return false - end + def check_already_under_debug + + end + + def switch_to_thread + + end + + def set_tbreak(str) + execute "tbreak #{str}" + end + + def continue + @pipe.puts 'c' + loop do + line = @pipe.readline + break if line =~ /__func_to_set_breakpoint_at/ end + get_response + end + + def call_start_attach + raise 'No main thread found. Did you forget to call `update_threads`?' if @main_thread == nil + @main_thread.switch + end + + def exit + execute 'q' + end + + def to_s + 'native_debugger' + end - def is_inside_gc(bt = get_bt) - if any_caller_match(bt, '(gc\.c)') - $stderr.puts "process #{$pid} is currently in garbage collection phase." - return true - else - return false +end + +class LLDB < NativeDebugger + + def initialize(executable, pid, options) + super(executable, pid, options) + end + + def set_flags + + end + + def update_threads + process_threads = [] + info_threads = (execute 'thread list').split("\n") + info_threads.each do |thread_info| + next unless thread_info =~ /[\s*]*thread\s#\d+.*/ + $stdout.puts "thread_info: #{thread_info}" + is_main = thread_info[0] == '*' + thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i + thread = ProcessThread.new(thread_num, is_main, self) + if thread.is_main + @main_thread = thread end + process_threads << thread end + process_threads + end - def need_finish_frame - bt = get_bt - return is_inside_malloc(bt) || is_inside_gc(bt) - end + def check_already_under_debug + threads = execute 'thread list' + threads =~ /ruby-debug-ide/ + end + + def switch_to_thread(thread_num) + execute "thread select #{thread_num}" + end + + def call_start_attach + super() + execute "expr (void *) dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" + execute "call start_attach(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\")" + end + + def to_s + 'lldb-3.8' + end +end + +class GDB < NativeDebugger + + def initialize(executable, pid, options) + super(executable, pid, options) end - def gdb.update_threads + def set_flags + execute 'set scheduler-locking off' # we will deadlock with it + execute 'set unwindonsignal on' # in case of some signal we will exit gdb + end + + def update_threads process_threads = [] - info_threads = (self.execute 'info threads').split("\n") - # first line of gdb's response is ` Id Target Id Frame` info line - # last line of gdb's response is `(gdb) ` - info_threads.shift - info_threads.pop + info_threads = (execute 'info threads').split("\n") # each thread info looks like this: # 3 Thread 0x7ff535405700 (LWP 8291) "ruby-timer-thr" 0x00007ff534a15fdd in poll () at ../sysdeps/unix/syscall-template.S:81 info_threads.each do |thread_info| next unless thread_info =~ /[\s*]*\d+\s+Thread.*/ - $stderr.puts "thread_info: #{thread_info}" + $stdout.puts "thread_info: #{thread_info}" is_main = thread_info[0] == '*' - thread_info.sub!(/[\s*]*/, '') - thread_info.sub!(/\s.*$/, '') - thread = ProcessThread.new(thread_info.to_i, is_main) + thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i + thread = ProcessThread.new(thread_num, is_main, self) if thread.is_main - $main_thread = thread + @main_thread = thread end process_threads << thread end process_threads end - def gdb.get_response - content = '' - loop do - sleep 0.01 # give time to gdb to finish command execution and print it to file - file = File.open($gdb_tmp_file, 'r') - content = file.read - file.close - break if content =~ /\(gdb\)\s\z/ - end - content + def check_already_under_debug + threads = execute 'info threads' + threads =~ /ruby-debug-ide/ end - def gdb.enable_logging - self.puts 'set logging on' + def switch_to_thread(thread_num) + execute "thread #{thread_num}" end - def gdb.disable_logging - self.puts 'set logging off' + def call_start_attach + super() + execute "call dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" + execute "call start_attach(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\")" end - def gdb.overwrite_file - disable_logging - enable_logging + def to_s + 'gdb' end - def gdb.execute(command) - self.overwrite_file - self.puts command - $stdout.puts "executed command '#{command}' inside gdb." - if command == 'q' - return '' - end - response = self.get_response - if command == 'bt' - $last_bt = response - end - return response +end + +class ProcessThread + + attr_reader :thread_num, :is_main + + def initialize(thread_num, is_main, native_debugger) + @thread_num = thread_num + @is_main = is_main + @native_debugger = native_debugger end - def gdb.finish - $stdout.puts 'trying to finish current frame.' - self.execute 'finish' + def switch + @native_debugger.switch_to_thread(thread_num) end - def gdb.set_logging - self.puts "set logging file #{$gdb_tmp_file}" - self.puts 'set logging overwrite on' - self.puts 'set logging redirect on' - self.enable_logging + def finish + @native_debugger.execute 'finish' + end - $stdout.puts "all gdb output redirected to #{$gdb_tmp_file}." + def get_bt + @native_debugger.execute 'bt' end - def gdb.check_already_under_debug - threads = self.execute 'info threads' - return threads =~ /ruby-debug-ide/ + def any_caller_match(bt, pattern) + bt =~ /#{pattern}/ end - gdb.set_logging + def is_inside_malloc(bt = get_bt) + if any_caller_match(bt, '(malloc\.c)') + $stderr.puts "process #{@native_debugger.pid} is currently inside malloc." + true + else + false + end + end - if gdb.check_already_under_debug - $stderr.puts "Process #{$pid} is already under debug" - gdb.execute 'q' + def is_inside_gc(bt = get_bt) + if any_caller_match(bt, '(gc\.c)') + $stderr.puts "process #{@native_debugger.pid} is currently in garbage collection phase." + true + else + false + end end - gdb.execute 'set scheduler-locking off' - gdb.execute 'set unwindonsignal on' + def need_finish_frame + bt = get_bt + is_inside_malloc(bt) || is_inside_gc(bt) + end - should_check_threads_state = true +end - while should_check_threads_state - should_check_threads_state = false - gdb.update_threads.each do |thread| - thread.switch - while thread.need_finish_frame - should_check_threads_state = true - thread.finish - end - end +def choose_debugger + if true + GDB.new(@options.ruby_path, @options.pid, '-nh -nx') + else + LLDB.new(@options.ruby_path, @options.pid, '--no-lldbinit') end +end - $main_thread.switch +gdb = choose_debugger +gdb.attach_to_process +gdb.set_flags - gdb.execute "call dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" - gdb.execute "call start_attach(\"require '#{path_to_debugger_loader}'; load_debugger(#{gems_to_include.gsub("\"", "'")}, #{argv.gsub("\"", "'")})\")" +if gdb.check_already_under_debug + $stderr.puts "Process #{gdb.pid} is already under debug" + gdb.exit + exit! +end - gdb_executed_all_commands = true - gdb.execute 'q' +should_check_threads_state = true +while should_check_threads_state + should_check_threads_state = false + gdb.update_threads.each do |thread| + thread.switch + while thread.need_finish_frame + should_check_threads_state = true + thread.finish + end + end end +gdb.call_start_attach +gdb.set_tbreak('__func_to_set_breakpoint_at') +gdb.continue +gdb.execute "call rb_eval_string_protect(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\", (int *)0)" +gdb.exit + trap('INT') do - unless gdb_executed_all_commands - $stderr.puts "Seems like could not attach to process. Its backtrace:\n#{$last_bt}" - $stderr.flush - end - exit 1 + $stderr.puts "Last backtrace:\n#{gdb.last_bt}" + exit! end -if options.uid - Process::Sys.setuid(options.uid.to_i) +if @options.uid + Process::Sys.setuid(@options.uid.to_i) end sleep diff --git a/ext/do_attach.c b/ext/do_attach.c index 7291b48..c29c9f6 100644 --- a/ext/do_attach.c +++ b/ext/do_attach.c @@ -12,6 +12,11 @@ __check_gc(void) return 0; } +static void +__func_to_set_breakpoint_at() +{ +} + static void __catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass) { @@ -23,15 +28,18 @@ __catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE rb_remove_event_hook(__catch_line_event); if (__check_gc()) return; - rb_eval_string_protect(_command_to_eval, NULL); // TODO pass something more useful than NULL + __func_to_set_breakpoint_at(); +// rb_eval_string_protect(_command_to_eval, NULL); // TODO pass something more useful than NULL } -void +int start_attach(const char* command) { + rb_eval_string("puts 'bla bla bla'"); _command_to_eval = command; if (__check_gc()) - return; + return 1; rb_global_variable((VALUE *) _command_to_eval); rb_add_event_hook(__catch_line_event, RUBY_EVENT_LINE, (VALUE) NULL); + return 2323; } diff --git a/ext/do_attach.h b/ext/do_attach.h index 3697d3f..5886935 100644 --- a/ext/do_attach.h +++ b/ext/do_attach.h @@ -5,6 +5,6 @@ #include #include -void start_attach(const char *command); +int start_attach(const char *command); #endif //__DO_ATTACH_H__ \ No newline at end of file From 36d3686d31106024082d6855bfdfd3c2cdfbe663 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Sun, 4 Sep 2016 22:07:20 +0300 Subject: [PATCH 163/302] some cosmetic changes + choosing with debugger to use --- bin/gdb_wrapper | 82 ++++++++++++++++++++++++++++++------------------- ext/do_attach.c | 10 ++---- ext/do_attach.h | 2 +- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 5482744..18c1c3e 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -59,19 +59,19 @@ end require 'ruby-debug-ide/greeter' Debugger::print_greeting_msg(nil, nil) -# this class is some kind of "interface" class NativeDebugger - attr_reader :pid, :last_bt + attr_reader :pid, :main_thread, :process_threads # @param executable -- path to ruby interpreter # @param pid -- pid of process you want to debug # @param options -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit) def initialize(executable, pid, options) @pid = pid - @main_thread = nil @delimiter = '__OUTPUT_FINISHED__' # for getting response - @last_bt = '' # to shaw it to user + @tbreak = '__func_to_set_breakpoint_at' + @main_thread = nil + @process_threads = nil launch_string = "#{self} #{executable} #{options}" @pipe = IO.popen(launch_string, 'r+') @@ -90,9 +90,6 @@ class NativeDebugger return '' end response = get_response - if command == 'bt' - @last_bt = response - end $stdout.puts "response for #{command}:\n#{response}\n\n\n\n" response end @@ -106,7 +103,7 @@ class NativeDebugger line = @pipe.readline $stderr.puts line next if line =~ /\(lldb\)/ # lldb repeats your input to its output - break if line =~ /\$\d+\s=\s"__OUTPUT_FINISHED__"/ + break if line =~ /\$\d+\s=\s"#{@delimiter}"/ content += line end content @@ -129,10 +126,12 @@ class NativeDebugger end def continue + $stdout.puts 'continuing' @pipe.puts 'c' loop do line = @pipe.readline - break if line =~ /__func_to_set_breakpoint_at/ + $stderr.puts line + break if line =~ /#{Regexp.escape(@tbreak)}/ end get_response end @@ -142,6 +141,15 @@ class NativeDebugger @main_thread.switch end + def wait_line_event + call_start_attach + continue + end + + def load_debugger + execute "call rb_eval_string_protect(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\", (int *)0)" + end + def exit execute 'q' end @@ -163,20 +171,20 @@ class LLDB < NativeDebugger end def update_threads - process_threads = [] + @process_threads = [] info_threads = (execute 'thread list').split("\n") info_threads.each do |thread_info| next unless thread_info =~ /[\s*]*thread\s#\d+.*/ $stdout.puts "thread_info: #{thread_info}" is_main = thread_info[0] == '*' thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i - thread = ProcessThread.new(thread_num, is_main, self) + thread = ProcessThread.new(thread_num, is_main, thread_info, self) if thread.is_main @main_thread = thread end - process_threads << thread + @process_threads << thread end - process_threads + @process_threads end def check_already_under_debug @@ -191,11 +199,12 @@ class LLDB < NativeDebugger def call_start_attach super() execute "expr (void *) dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" - execute "call start_attach(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\")" + execute 'call start_attach()' + set_tbreak(@tbreak) end def to_s - 'lldb-3.8' + 'lldb' end end @@ -212,22 +221,20 @@ class GDB < NativeDebugger end def update_threads - process_threads = [] + @process_threads = [] info_threads = (execute 'info threads').split("\n") - # each thread info looks like this: - # 3 Thread 0x7ff535405700 (LWP 8291) "ruby-timer-thr" 0x00007ff534a15fdd in poll () at ../sysdeps/unix/syscall-template.S:81 info_threads.each do |thread_info| next unless thread_info =~ /[\s*]*\d+\s+Thread.*/ $stdout.puts "thread_info: #{thread_info}" is_main = thread_info[0] == '*' thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i - thread = ProcessThread.new(thread_num, is_main, self) + thread = ProcessThread.new(thread_num, is_main, thread_info, self) if thread.is_main @main_thread = thread end - process_threads << thread + @process_threads << thread end - process_threads + @process_threads end def check_already_under_debug @@ -242,7 +249,8 @@ class GDB < NativeDebugger def call_start_attach super() execute "call dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" - execute "call start_attach(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\")" + execute 'call start_attach()' + set_tbreak(@tbreak) end def to_s @@ -253,12 +261,14 @@ end class ProcessThread - attr_reader :thread_num, :is_main + attr_reader :thread_num, :is_main, :thread_info, :last_bt - def initialize(thread_num, is_main, native_debugger) + def initialize(thread_num, is_main, thread_info, native_debugger) @thread_num = thread_num @is_main = is_main @native_debugger = native_debugger + @thread_info = thread_info + @last_bt = nil end def switch @@ -270,7 +280,7 @@ class ProcessThread end def get_bt - @native_debugger.execute 'bt' + @last_bt = @native_debugger.execute 'bt' end def any_caller_match(bt, pattern) @@ -302,11 +312,19 @@ class ProcessThread end +def exists_command(command) + `command -v #{command} >/dev/null 2>&1 || { exit 1; }` + $?.exitstatus == 0 +end + def choose_debugger - if true + $stderr.puts "exists: #{exists_command('gdb')}, #{exists_command('lldb')}" + if exists_command('gdb') GDB.new(@options.ruby_path, @options.pid, '-nh -nx') - else + elsif exists_command('lldb') LLDB.new(@options.ruby_path, @options.pid, '--no-lldbinit') + else + raise 'Neither gdb nor lldb was found. Aborting.' end end @@ -333,14 +351,14 @@ while should_check_threads_state end end -gdb.call_start_attach -gdb.set_tbreak('__func_to_set_breakpoint_at') -gdb.continue -gdb.execute "call rb_eval_string_protect(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\", (int *)0)" +gdb.wait_line_event +gdb.load_debugger gdb.exit trap('INT') do - $stderr.puts "Last backtrace:\n#{gdb.last_bt}" + gdb.process_threads.each do |thread| + $stderr.puts "Last backtrace for thread #{thread.thread_info}:\n#{thread.last_bt}" + end exit! end diff --git a/ext/do_attach.c b/ext/do_attach.c index c29c9f6..6778efc 100644 --- a/ext/do_attach.c +++ b/ext/do_attach.c @@ -1,7 +1,5 @@ #include "do_attach.h" -static const char *_command_to_eval; - static int __check_gc(void) { @@ -29,17 +27,13 @@ __catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE if (__check_gc()) return; __func_to_set_breakpoint_at(); -// rb_eval_string_protect(_command_to_eval, NULL); // TODO pass something more useful than NULL } int -start_attach(const char* command) +start_attach() { - rb_eval_string("puts 'bla bla bla'"); - _command_to_eval = command; if (__check_gc()) return 1; - rb_global_variable((VALUE *) _command_to_eval); rb_add_event_hook(__catch_line_event, RUBY_EVENT_LINE, (VALUE) NULL); - return 2323; + return 0; } diff --git a/ext/do_attach.h b/ext/do_attach.h index 5886935..e9e5603 100644 --- a/ext/do_attach.h +++ b/ext/do_attach.h @@ -5,6 +5,6 @@ #include #include -int start_attach(const char *command); +int start_attach(); #endif //__DO_ATTACH_H__ \ No newline at end of file From 096cd724eface3178d38320dd0c0d7e040bf307d Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 5 Sep 2016 15:07:48 +0300 Subject: [PATCH 164/302] printing backtrace of all threads in case of fail + some minor chages --- bin/gdb_wrapper | 66 +++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 18c1c3e..abe68ba 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -61,7 +61,7 @@ Debugger::print_greeting_msg(nil, nil) class NativeDebugger - attr_reader :pid, :main_thread, :process_threads + attr_reader :pid, :main_thread, :process_threads, :pipe # @param executable -- path to ruby interpreter # @param pid -- pid of process you want to debug @@ -89,9 +89,7 @@ class NativeDebugger @pipe.close return '' end - response = get_response - $stdout.puts "response for #{command}:\n#{response}\n\n\n\n" - response + get_response end def get_response @@ -101,7 +99,6 @@ class NativeDebugger content = '' loop do line = @pipe.readline - $stderr.puts line next if line =~ /\(lldb\)/ # lldb repeats your input to its output break if line =~ /\$\d+\s=\s"#{@delimiter}"/ content += line @@ -152,6 +149,7 @@ class NativeDebugger def exit execute 'q' + @pipe.close end def to_s @@ -312,29 +310,44 @@ class ProcessThread end -def exists_command(command) +def command_exists(command) `command -v #{command} >/dev/null 2>&1 || { exit 1; }` $?.exitstatus == 0 end def choose_debugger - $stderr.puts "exists: #{exists_command('gdb')}, #{exists_command('lldb')}" - if exists_command('gdb') - GDB.new(@options.ruby_path, @options.pid, '-nh -nx') - elsif exists_command('lldb') - LLDB.new(@options.ruby_path, @options.pid, '--no-lldbinit') + if command_exists('gdb') + debugger = GDB.new(@options.ruby_path, @options.pid, '-nh -nx') + elsif command_exists('lldb') + debugger = LLDB.new(@options.ruby_path, @options.pid, '--no-lldbinit') else raise 'Neither gdb nor lldb was found. Aborting.' end + + trap('INT') do + unless debugger.pipe.closed? + $stderr.puts "backtraces for threads:\n\n" + debugger.process_threads.each do |thread| + $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" + end + end + exit! + end + + debugger end -gdb = choose_debugger -gdb.attach_to_process -gdb.set_flags +debugger = choose_debugger +debugger.attach_to_process +debugger.set_flags -if gdb.check_already_under_debug - $stderr.puts "Process #{gdb.pid} is already under debug" - gdb.exit +if @options.uid + Process::Sys.setuid(@options.uid.to_i) +end + +if debugger.check_already_under_debug + $stderr.puts "Process #{debugger.pid} is already under debug" + debugger.exit exit! end @@ -342,7 +355,7 @@ should_check_threads_state = true while should_check_threads_state should_check_threads_state = false - gdb.update_threads.each do |thread| + debugger.update_threads.each do |thread| thread.switch while thread.need_finish_frame should_check_threads_state = true @@ -351,19 +364,8 @@ while should_check_threads_state end end -gdb.wait_line_event -gdb.load_debugger -gdb.exit - -trap('INT') do - gdb.process_threads.each do |thread| - $stderr.puts "Last backtrace for thread #{thread.thread_info}:\n#{thread.last_bt}" - end - exit! -end - -if @options.uid - Process::Sys.setuid(@options.uid.to_i) -end +debugger.wait_line_event +debugger.load_debugger +debugger.exit sleep From c0668953ac07df8addb5158d96728d375145e5a2 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Tue, 6 Sep 2016 11:11:39 +0300 Subject: [PATCH 165/302] little refactoring. deleted unused functions. --- bin/gdb_wrapper | 1 - ext/Makefile | 4 ++-- ext/{do_attach.c => attach.c} | 16 +++------------- ext/attach.h | 9 +++++++++ ext/do_attach.h | 10 ---------- 5 files changed, 14 insertions(+), 26 deletions(-) rename ext/{do_attach.c => attach.c} (64%) create mode 100644 ext/attach.h delete mode 100644 ext/do_attach.h diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index abe68ba..308dacd 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -127,7 +127,6 @@ class NativeDebugger @pipe.puts 'c' loop do line = @pipe.readline - $stderr.puts line break if line =~ /#{Regexp.escape(@tbreak)}/ end get_response diff --git a/ext/Makefile b/ext/Makefile index 9bec56c..6c52c90 100644 --- a/ext/Makefile +++ b/ext/Makefile @@ -3,8 +3,8 @@ all: libAttach.so libAttach.so: libAttach.o gcc -shared -o libAttach.so libAttach.o -libAttach.o: do_attach.c - gcc -Wall -g -fPIC -c -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0 -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0/x86_64-linux/ do_attach.c -o libAttach.o +libAttach.o: attach.c + gcc -Wall -g -fPIC -c -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0 -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0/x86_64-linux/ attach.c -o libAttach.o clean: rm libAttach.* diff --git a/ext/do_attach.c b/ext/attach.c similarity index 64% rename from ext/do_attach.c rename to ext/attach.c index 6778efc..d4d4dbe 100644 --- a/ext/do_attach.c +++ b/ext/attach.c @@ -1,14 +1,4 @@ -#include "do_attach.h" - -static int -__check_gc(void) -{ - if (rb_during_gc()) { - fprintf(stderr, "Can not connect during garbage collection phase. Please, try again later.\n"); - return 1; - } - return 0; -} +#include "attach.h" static void __func_to_set_breakpoint_at() @@ -24,7 +14,7 @@ __catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE (void)sizeof(klass); rb_remove_event_hook(__catch_line_event); - if (__check_gc()) + if (rb_during_gc()) return; __func_to_set_breakpoint_at(); } @@ -32,7 +22,7 @@ __catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE int start_attach() { - if (__check_gc()) + if (rb_during_gc()) return 1; rb_add_event_hook(__catch_line_event, RUBY_EVENT_LINE, (VALUE) NULL); return 0; diff --git a/ext/attach.h b/ext/attach.h new file mode 100644 index 0000000..9c98192 --- /dev/null +++ b/ext/attach.h @@ -0,0 +1,9 @@ +#ifndef __ATTACH_H__ +#define __ATTACH_H__ + +#include +#include + +int start_attach(); + +#endif //__ATTACH_H__ \ No newline at end of file diff --git a/ext/do_attach.h b/ext/do_attach.h deleted file mode 100644 index e9e5603..0000000 --- a/ext/do_attach.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __DO_ATTACH_H__ -#define __DO_ATTACH_H__ - -#include -#include -#include - -int start_attach(); - -#endif //__DO_ATTACH_H__ \ No newline at end of file From cede1279387a54c42002b5a5eb623173f29baaf8 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Wed, 7 Sep 2016 14:59:38 +0300 Subject: [PATCH 166/302] finding attach.so file in debase added --- bin/gdb_wrapper | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 308dacd..dbe2f2c 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -6,7 +6,7 @@ require 'ostruct' $stdout.sync = true $stderr.sync = true -@options = OpenStruct.new( +$options = OpenStruct.new( 'pid' => nil, 'sdk_path' => nil, 'uid' => nil, @@ -20,39 +20,39 @@ Some useful banner. EOB opts.on('--pid PID', 'pid of process you want to attach to for debugging') do |pid| - @options.pid = pid + $options.pid = pid end opts.on('--ruby-path RUBY_PATH', 'path to ruby interpreter') do |ruby_path| - @options.ruby_path = ruby_path + $options.ruby_path = ruby_path end opts.on('--uid UID', 'uid which this process should set after executing gdb attach') do |uid| - @options.uid = uid + $options.uid = uid end opts.on('--include-gem GEM_LIB_PATH', 'lib of gem to include') do |gem_lib_path| - @options.gems_to_include << gem_lib_path + $options.gems_to_include << gem_lib_path end end opts.parse! ARGV -unless @options.pid +unless $options.pid $stderr.puts 'You should specify PID of process you want to attach to' exit 1 end -unless @options.ruby_path +unless $options.ruby_path $stderr.puts 'You should specify path to the ruby interpreter' exit 1 end $argv = '["' + ARGV * '", "' + '"]' -$gems_to_include = '["' + @options.gems_to_include * '", "' + '"]' +$gems_to_include = '["' + $options.gems_to_include * '", "' + '"]' $path_to_debugger_loader = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' -@options.gems_to_include.each do |gem_path| +$options.gems_to_include.each do |gem_path| $LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path) end @@ -72,6 +72,11 @@ class NativeDebugger @tbreak = '__func_to_set_breakpoint_at' @main_thread = nil @process_threads = nil + debase_path = $options.gems_to_include.select {|gem_path| gem_path =~ /debase/} + if debase_path.size == 0 + raise 'No debase gem found.' + end + @path_to_attach = debase_path[0] + '/attach.so' launch_string = "#{self} #{executable} #{options}" @pipe = IO.popen(launch_string, 'r+') @@ -195,7 +200,7 @@ class LLDB < NativeDebugger def call_start_attach super() - execute "expr (void *) dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" + execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)" execute 'call start_attach()' set_tbreak(@tbreak) end @@ -245,7 +250,7 @@ class GDB < NativeDebugger def call_start_attach super() - execute "call dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)" + execute "call dlopen(\"#{@path_to_attach}\", 2)" execute 'call start_attach()' set_tbreak(@tbreak) end @@ -316,9 +321,9 @@ end def choose_debugger if command_exists('gdb') - debugger = GDB.new(@options.ruby_path, @options.pid, '-nh -nx') + debugger = GDB.new($options.ruby_path, $options.pid, '-nh -nx') elsif command_exists('lldb') - debugger = LLDB.new(@options.ruby_path, @options.pid, '--no-lldbinit') + debugger = LLDB.new($options.ruby_path, $options.pid, '--no-lldbinit') else raise 'Neither gdb nor lldb was found. Aborting.' end @@ -340,8 +345,8 @@ debugger = choose_debugger debugger.attach_to_process debugger.set_flags -if @options.uid - Process::Sys.setuid(@options.uid.to_i) +if $options.uid + Process::Sys.setuid($options.uid.to_i) end if debugger.check_already_under_debug From ea4af282cc07eb909c04f2700456af36a809876f Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Fri, 9 Sep 2016 21:29:51 +0300 Subject: [PATCH 167/302] bug fix: no need to close already closed stream (it works well only starting from ruby 2.3) --- bin/gdb_wrapper | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index dbe2f2c..d20f700 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -91,7 +91,6 @@ class NativeDebugger @pipe.puts command $stdout.puts "executed `#{command}` command inside #{self}." if command == 'q' - @pipe.close return '' end get_response From 7a15facd8663de89b4cbfa961b43ab6c255272a3 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 12 Sep 2016 00:54:50 +0300 Subject: [PATCH 168/302] replaced global variables with local ones --- bin/gdb_wrapper | 55 ++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index d20f700..08c37d2 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -6,7 +6,7 @@ require 'ostruct' $stdout.sync = true $stderr.sync = true -$options = OpenStruct.new( +options = OpenStruct.new( 'pid' => nil, 'sdk_path' => nil, 'uid' => nil, @@ -20,39 +20,38 @@ Some useful banner. EOB opts.on('--pid PID', 'pid of process you want to attach to for debugging') do |pid| - $options.pid = pid + options.pid = pid end opts.on('--ruby-path RUBY_PATH', 'path to ruby interpreter') do |ruby_path| - $options.ruby_path = ruby_path + options.ruby_path = ruby_path end opts.on('--uid UID', 'uid which this process should set after executing gdb attach') do |uid| - $options.uid = uid + options.uid = uid end opts.on('--include-gem GEM_LIB_PATH', 'lib of gem to include') do |gem_lib_path| - $options.gems_to_include << gem_lib_path + options.gems_to_include << gem_lib_path end end opts.parse! ARGV -unless $options.pid +unless options.pid $stderr.puts 'You should specify PID of process you want to attach to' exit 1 end -unless $options.ruby_path +unless options.ruby_path $stderr.puts 'You should specify path to the ruby interpreter' exit 1 end -$argv = '["' + ARGV * '", "' + '"]' -$gems_to_include = '["' + $options.gems_to_include * '", "' + '"]' -$path_to_debugger_loader = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' +argv = '["' + ARGV * '", "' + '"]' +debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' -$options.gems_to_include.each do |gem_path| +options.gems_to_include.each do |gem_path| $LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path) end @@ -65,20 +64,24 @@ class NativeDebugger # @param executable -- path to ruby interpreter # @param pid -- pid of process you want to debug - # @param options -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit) - def initialize(executable, pid, options) + # @param flags -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit) + def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) @pid = pid @delimiter = '__OUTPUT_FINISHED__' # for getting response @tbreak = '__func_to_set_breakpoint_at' @main_thread = nil @process_threads = nil - debase_path = $options.gems_to_include.select {|gem_path| gem_path =~ /debase/} + debase_path = gems_to_include.select {|gem_path| gem_path =~ /debase/} if debase_path.size == 0 raise 'No debase gem found.' end @path_to_attach = debase_path[0] + '/attach.so' - launch_string = "#{self} #{executable} #{options}" + @gems_to_include = '["' + gems_to_include * '", "' + '"]' + @debugger_loader_path = debugger_loader_path + @argv = argv + + launch_string = "#{self} #{executable} #{flags}" @pipe = IO.popen(launch_string, 'r+') $stdout.puts "executed '#{launch_string}'" end @@ -147,7 +150,7 @@ class NativeDebugger end def load_debugger - execute "call rb_eval_string_protect(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\", (int *)0)" + execute "call rb_eval_string_protect(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" end def exit @@ -163,8 +166,8 @@ end class LLDB < NativeDebugger - def initialize(executable, pid, options) - super(executable, pid, options) + def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + super(executable, pid, flags, gems_to_include, debugger_loader_path, argv) end def set_flags @@ -212,8 +215,8 @@ end class GDB < NativeDebugger - def initialize(executable, pid, options) - super(executable, pid, options) + def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + super(executable, pid, flags, gems_to_include, debugger_loader_path, argv) end def set_flags @@ -318,11 +321,11 @@ def command_exists(command) $?.exitstatus == 0 end -def choose_debugger +def choose_debugger(ruby_path, pid, gems_to_include, debugger_loader_path, argv) if command_exists('gdb') - debugger = GDB.new($options.ruby_path, $options.pid, '-nh -nx') + debugger = GDB.new(ruby_path, pid, '-nh -nx', gems_to_include, debugger_loader_path, argv) elsif command_exists('lldb') - debugger = LLDB.new($options.ruby_path, $options.pid, '--no-lldbinit') + debugger = LLDB.new(ruby_path, pid, '--no-lldbinit', gems_to_include, debugger_loader_path, argv) else raise 'Neither gdb nor lldb was found. Aborting.' end @@ -340,12 +343,12 @@ def choose_debugger debugger end -debugger = choose_debugger +debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv) debugger.attach_to_process debugger.set_flags -if $options.uid - Process::Sys.setuid($options.uid.to_i) +if options.uid + Process::Sys.setuid(options.uid.to_i) end if debugger.check_already_under_debug From d91c3d1fe742c19ecf53ec3059fb27e616870ca7 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Thu, 29 Sep 2016 22:30:51 +0300 Subject: [PATCH 169/302] added debug output if `--debug` key specified. --- bin/gdb_wrapper | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 08c37d2..510d30f 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -13,6 +13,30 @@ options = OpenStruct.new( 'gems_to_include' => [] ) +module DebugPrinter + + class << self + attr_accessor :cli_debug + + def print_debug(msg) + if DebugPrinter.cli_debug + delimiter = '=' * 10 + upper_border = "\n#{delimiter}\n" + lower_border = "#{delimiter}\n\n" + + if msg.length > 0 and msg[msg.length - 1] != "\n" + lower_border = "\n" + lower_border + end + + $stdout.puts upper_border + msg + lower_border + end + end + end + +end + +DebugPrinter.cli_debug = ARGV.include? '--debug' + opts = OptionParser.new do |opts| # TODO need some banner opts.banner = </dev/null 2>&1 || { exit 1; }` + if $?.exitstatus != 0 + DebugPrinter.print_debug("#{checking_command}command does not exist.") + else + DebugPrinter.print_debug("#{checking_command}command does exist.") + end $?.exitstatus == 0 end @@ -348,6 +381,7 @@ debugger.attach_to_process debugger.set_flags if options.uid + DebugPrinter.print_debug("changing current uid from #{Process.uid} to #{options.uid}") Process::Sys.setuid(options.uid.to_i) end From 9026873991e19167cc7aef428b03eb3e97514b91 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Thu, 29 Sep 2016 22:50:00 +0300 Subject: [PATCH 170/302] It is essential for lldb connecting to OS X's ruby process to specify function type. Under OS X (due to compilation keys, I guess) lldb does not know type of ruby functions so we need to write them explicitly. --- bin/gdb_wrapper | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 510d30f..d530811 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -105,6 +105,8 @@ class NativeDebugger @debugger_loader_path = debugger_loader_path @argv = argv + @eval_string = "rb_eval_string_protect(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" + launch_string = "#{self} #{executable} #{flags}" @pipe = IO.popen(launch_string, 'r+') $stdout.puts "executed '#{launch_string}'" @@ -177,7 +179,7 @@ class NativeDebugger end def load_debugger - execute "call rb_eval_string_protect(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" + end def exit @@ -230,10 +232,14 @@ class LLDB < NativeDebugger def call_start_attach super() execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)" - execute 'call start_attach()' + execute 'expr (int) start_attach()' set_tbreak(@tbreak) end + def load_debugger + execute "expr (VALUE) #{@eval_string}" + end + def to_s 'lldb' end @@ -284,6 +290,10 @@ class GDB < NativeDebugger set_tbreak(@tbreak) end + def load_debugger + execute "call #{@eval_string}" + end + def to_s 'gdb' end From 6ae52eef42c62ea3b2f443abb44dfbe7d314ab1a Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Thu, 29 Sep 2016 23:01:20 +0300 Subject: [PATCH 171/302] Gdb does not understand ruby symbol table under OS X (I guess it does not understand darwin debug format). That make it essential to prefer lldb over gdb (lldb works fine). --- bin/gdb_wrapper | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index d530811..84d7fe3 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -365,10 +365,10 @@ def command_exists(command) end def choose_debugger(ruby_path, pid, gems_to_include, debugger_loader_path, argv) - if command_exists('gdb') - debugger = GDB.new(ruby_path, pid, '-nh -nx', gems_to_include, debugger_loader_path, argv) - elsif command_exists('lldb') + if command_exists('lldb') debugger = LLDB.new(ruby_path, pid, '--no-lldbinit', gems_to_include, debugger_loader_path, argv) + elsif command_exists('gdb') + debugger = GDB.new(ruby_path, pid, '-nh -nx', gems_to_include, debugger_loader_path, argv) else raise 'Neither gdb nor lldb was found. Aborting.' end From c03250eabf1f7120f1118304afdb9a6eb1b50bff Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Thu, 29 Sep 2016 23:12:53 +0300 Subject: [PATCH 172/302] Attach lib can have different extension than '.so' (e.g. '.bundle' under OS X). So we need to find appropriate one manually. --- bin/gdb_wrapper | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 84d7fe3..d222965 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -99,7 +99,7 @@ class NativeDebugger if debase_path.size == 0 raise 'No debase gem found.' end - @path_to_attach = debase_path[0] + '/attach.so' + @path_to_attach = find_attach_lib(debase_path[0]) @gems_to_include = '["' + gems_to_include * '", "' + '"]' @debugger_loader_path = debugger_loader_path @@ -112,6 +112,18 @@ class NativeDebugger $stdout.puts "executed '#{launch_string}'" end + def find_attach_lib(debase_path) + attach_lib = debase_path + '/attach' + known_extensions = %w(.so .bundle .dll) + known_extensions.each do |ext| + if File.file?(attach_lib + ext) + return attach_lib + ext + end + end + + raise 'Could not find attach library' + end + def attach_to_process execute "attach #{@pid}" end From f3955ca4f99990707ae8d240f9feda72c58d14cc Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Tue, 4 Oct 2016 14:54:04 +0300 Subject: [PATCH 173/302] fixes for lldb-3.6. `print` does not work there. output works bad after `thread select`. replaced debug output with more representative. --- bin/gdb_wrapper | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index d222965..4fdf002 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -20,15 +20,7 @@ module DebugPrinter def print_debug(msg) if DebugPrinter.cli_debug - delimiter = '=' * 10 - upper_border = "\n#{delimiter}\n" - lower_border = "#{delimiter}\n\n" - - if msg.length > 0 and msg[msg.length - 1] != "\n" - lower_border = "\n" + lower_border - end - - $stdout.puts upper_border + msg + lower_border + $stderr.puts msg end end end @@ -139,18 +131,17 @@ class NativeDebugger def get_response # we need this hack to understand that debugger gave us all output from last executed command - @pipe.puts "print \"#{@delimiter}\"" + print_delimiter content = '' loop do line = @pipe.readline + break if check_delimiter(line) + DebugPrinter.print_debug('respond line: ' + line) next if line =~ /\(lldb\)/ # lldb repeats your input to its output - break if line =~ /\$\d+\s=\s"#{@delimiter}"/ content += line end - DebugPrinter.print_debug(content) - content end @@ -162,6 +153,14 @@ class NativeDebugger end + def print_delimiter + + end + + def check_delimiter(line) + + end + def switch_to_thread end @@ -220,7 +219,6 @@ class LLDB < NativeDebugger info_threads = (execute 'thread list').split("\n") info_threads.each do |thread_info| next unless thread_info =~ /[\s*]*thread\s#\d+.*/ - $stdout.puts "thread_info: #{thread_info}" is_main = thread_info[0] == '*' thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i thread = ProcessThread.new(thread_num, is_main, thread_info, self) @@ -248,6 +246,14 @@ class LLDB < NativeDebugger set_tbreak(@tbreak) end + def print_delimiter + @pipe.puts "script print \"#{@delimiter}\"" + end + + def check_delimiter(line) + line =~ /#{@delimiter}$/ + end + def load_debugger execute "expr (VALUE) #{@eval_string}" end @@ -302,6 +308,14 @@ class GDB < NativeDebugger set_tbreak(@tbreak) end + def print_delimiter + @pipe.puts "print \"#{@delimiter}\"" + end + + def check_delimiter(line) + line =~ /\$\d+\s=\s"#{@delimiter}"/ + end + def load_debugger execute "call #{@eval_string}" end From 705c66f1814e09ee9b3f7c58a6957aef32216133 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 10 Oct 2016 16:32:05 +0300 Subject: [PATCH 174/302] refactoring: separated debuggers and util methods --- bin/gdb_wrapper | 340 +------------------ lib/ruby-debug-ide/attach/gdb.rb | 69 ++++ lib/ruby-debug-ide/attach/lldb.rb | 67 ++++ lib/ruby-debug-ide/attach/native_debugger.rb | 129 +++++++ lib/ruby-debug-ide/attach/process_thread.rb | 54 +++ lib/ruby-debug-ide/attach/util.rb | 35 ++ 6 files changed, 357 insertions(+), 337 deletions(-) create mode 100644 lib/ruby-debug-ide/attach/gdb.rb create mode 100644 lib/ruby-debug-ide/attach/lldb.rb create mode 100644 lib/ruby-debug-ide/attach/native_debugger.rb create mode 100644 lib/ruby-debug-ide/attach/process_thread.rb create mode 100644 lib/ruby-debug-ide/attach/util.rb diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 4fdf002..905e741 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -74,343 +74,9 @@ end require 'ruby-debug-ide/greeter' Debugger::print_greeting_msg(nil, nil) -class NativeDebugger - - attr_reader :pid, :main_thread, :process_threads, :pipe - - # @param executable -- path to ruby interpreter - # @param pid -- pid of process you want to debug - # @param flags -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit) - def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) - @pid = pid - @delimiter = '__OUTPUT_FINISHED__' # for getting response - @tbreak = '__func_to_set_breakpoint_at' - @main_thread = nil - @process_threads = nil - debase_path = gems_to_include.select {|gem_path| gem_path =~ /debase/} - if debase_path.size == 0 - raise 'No debase gem found.' - end - @path_to_attach = find_attach_lib(debase_path[0]) - - @gems_to_include = '["' + gems_to_include * '", "' + '"]' - @debugger_loader_path = debugger_loader_path - @argv = argv - - @eval_string = "rb_eval_string_protect(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" - - launch_string = "#{self} #{executable} #{flags}" - @pipe = IO.popen(launch_string, 'r+') - $stdout.puts "executed '#{launch_string}'" - end - - def find_attach_lib(debase_path) - attach_lib = debase_path + '/attach' - known_extensions = %w(.so .bundle .dll) - known_extensions.each do |ext| - if File.file?(attach_lib + ext) - return attach_lib + ext - end - end - - raise 'Could not find attach library' - end - - def attach_to_process - execute "attach #{@pid}" - end - - def execute(command) - @pipe.puts command - $stdout.puts "executed `#{command}` command inside #{self}." - if command == 'q' - return '' - end - get_response - end - - def get_response - # we need this hack to understand that debugger gave us all output from last executed command - print_delimiter - - content = '' - loop do - line = @pipe.readline - break if check_delimiter(line) - DebugPrinter.print_debug('respond line: ' + line) - next if line =~ /\(lldb\)/ # lldb repeats your input to its output - content += line - end - - content - end - - def update_threads - - end - - def check_already_under_debug - - end - - def print_delimiter - - end - - def check_delimiter(line) - - end - - def switch_to_thread - - end - - def set_tbreak(str) - execute "tbreak #{str}" - end - - def continue - $stdout.puts 'continuing' - @pipe.puts 'c' - loop do - line = @pipe.readline - break if line =~ /#{Regexp.escape(@tbreak)}/ - end - get_response - end - - def call_start_attach - raise 'No main thread found. Did you forget to call `update_threads`?' if @main_thread == nil - @main_thread.switch - end - - def wait_line_event - call_start_attach - continue - end - - def load_debugger - - end - - def exit - execute 'q' - @pipe.close - end - - def to_s - 'native_debugger' - end - -end - -class LLDB < NativeDebugger - - def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) - super(executable, pid, flags, gems_to_include, debugger_loader_path, argv) - end - - def set_flags - - end - - def update_threads - @process_threads = [] - info_threads = (execute 'thread list').split("\n") - info_threads.each do |thread_info| - next unless thread_info =~ /[\s*]*thread\s#\d+.*/ - is_main = thread_info[0] == '*' - thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i - thread = ProcessThread.new(thread_num, is_main, thread_info, self) - if thread.is_main - @main_thread = thread - end - @process_threads << thread - end - @process_threads - end - - def check_already_under_debug - threads = execute 'thread list' - threads =~ /ruby-debug-ide/ - end - - def switch_to_thread(thread_num) - execute "thread select #{thread_num}" - end - - def call_start_attach - super() - execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)" - execute 'expr (int) start_attach()' - set_tbreak(@tbreak) - end - - def print_delimiter - @pipe.puts "script print \"#{@delimiter}\"" - end - - def check_delimiter(line) - line =~ /#{@delimiter}$/ - end - - def load_debugger - execute "expr (VALUE) #{@eval_string}" - end - - def to_s - 'lldb' - end - -end - -class GDB < NativeDebugger - - def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) - super(executable, pid, flags, gems_to_include, debugger_loader_path, argv) - end - - def set_flags - execute 'set scheduler-locking off' # we will deadlock with it - execute 'set unwindonsignal on' # in case of some signal we will exit gdb - end - - def update_threads - @process_threads = [] - info_threads = (execute 'info threads').split("\n") - info_threads.each do |thread_info| - next unless thread_info =~ /[\s*]*\d+\s+Thread.*/ - $stdout.puts "thread_info: #{thread_info}" - is_main = thread_info[0] == '*' - thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i - thread = ProcessThread.new(thread_num, is_main, thread_info, self) - if thread.is_main - @main_thread = thread - end - @process_threads << thread - end - @process_threads - end - - def check_already_under_debug - threads = execute 'info threads' - threads =~ /ruby-debug-ide/ - end - - def switch_to_thread(thread_num) - execute "thread #{thread_num}" - end - - def call_start_attach - super() - execute "call dlopen(\"#{@path_to_attach}\", 2)" - execute 'call start_attach()' - set_tbreak(@tbreak) - end - - def print_delimiter - @pipe.puts "print \"#{@delimiter}\"" - end - - def check_delimiter(line) - line =~ /\$\d+\s=\s"#{@delimiter}"/ - end - - def load_debugger - execute "call #{@eval_string}" - end - - def to_s - 'gdb' - end - -end - -class ProcessThread - - attr_reader :thread_num, :is_main, :thread_info, :last_bt - - def initialize(thread_num, is_main, thread_info, native_debugger) - @thread_num = thread_num - @is_main = is_main - @native_debugger = native_debugger - @thread_info = thread_info - @last_bt = nil - end - - def switch - @native_debugger.switch_to_thread(thread_num) - end - - def finish - @native_debugger.execute 'finish' - end - - def get_bt - @last_bt = @native_debugger.execute 'bt' - end - - def any_caller_match(bt, pattern) - bt =~ /#{pattern}/ - end - - def is_inside_malloc(bt = get_bt) - if any_caller_match(bt, '(malloc\.c)') - $stderr.puts "process #{@native_debugger.pid} is currently inside malloc." - true - else - false - end - end - - def is_inside_gc(bt = get_bt) - if any_caller_match(bt, '(gc\.c)') - $stderr.puts "process #{@native_debugger.pid} is currently in garbage collection phase." - true - else - false - end - end - - def need_finish_frame - bt = get_bt - is_inside_malloc(bt) || is_inside_gc(bt) - end - -end - -def command_exists(command) - checking_command = "checking command #{command} for existence\n" - `command -v #{command} >/dev/null 2>&1 || { exit 1; }` - if $?.exitstatus != 0 - DebugPrinter.print_debug("#{checking_command}command does not exist.") - else - DebugPrinter.print_debug("#{checking_command}command does exist.") - end - $?.exitstatus == 0 -end - -def choose_debugger(ruby_path, pid, gems_to_include, debugger_loader_path, argv) - if command_exists('lldb') - debugger = LLDB.new(ruby_path, pid, '--no-lldbinit', gems_to_include, debugger_loader_path, argv) - elsif command_exists('gdb') - debugger = GDB.new(ruby_path, pid, '-nh -nx', gems_to_include, debugger_loader_path, argv) - else - raise 'Neither gdb nor lldb was found. Aborting.' - end - - trap('INT') do - unless debugger.pipe.closed? - $stderr.puts "backtraces for threads:\n\n" - debugger.process_threads.each do |thread| - $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" - end - end - exit! - end - - debugger -end +require 'ruby-debug-ide/attach/util' +require 'ruby-debug-ide/attach/native_debugger' +require 'ruby-debug-ide/attach/process_thread' debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv) debugger.attach_to_process diff --git a/lib/ruby-debug-ide/attach/gdb.rb b/lib/ruby-debug-ide/attach/gdb.rb new file mode 100644 index 0000000..a507880 --- /dev/null +++ b/lib/ruby-debug-ide/attach/gdb.rb @@ -0,0 +1,69 @@ +require 'ruby-debug-ide/attach/native_debugger' + +class GDB < NativeDebugger + + def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + super(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + end + + def set_flags + execute 'set scheduler-locking off' # we will deadlock with it + execute 'set unwindonsignal on' # in case of some signal we will exit gdb + end + + def update_threads + @process_threads = [] + info_threads = (execute 'info threads').split("\n") + info_threads.each do |thread_info| + next unless thread_info =~ /[\s*]*\d+\s+Thread.*/ + $stdout.puts "thread_info: #{thread_info}" + is_main = thread_info[0] == '*' + thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i + thread = ProcessThread.new(thread_num, is_main, thread_info, self) + if thread.is_main + @main_thread = thread + end + @process_threads << thread + end + @process_threads + end + + def check_already_under_debug + threads = execute 'info threads' + threads =~ /ruby-debug-ide/ + end + + def switch_to_thread(thread_num) + execute "thread #{thread_num}" + end + + def call_start_attach + super() + execute "call dlopen(\"#{@path_to_attach}\", 2)" + execute 'call start_attach()' + set_tbreak(@tbreak) + end + + def print_delimiter + @pipe.puts "print \"#{@delimiter}\"" + end + + def check_delimiter(line) + line =~ /\$\d+\s=\s"#{@delimiter}"/ + end + + def load_debugger + execute "call #{@eval_string}" + end + + def to_s + GDB.to_s + end + + class << self + def to_s + 'gdb' + end + end + +end diff --git a/lib/ruby-debug-ide/attach/lldb.rb b/lib/ruby-debug-ide/attach/lldb.rb new file mode 100644 index 0000000..87245df --- /dev/null +++ b/lib/ruby-debug-ide/attach/lldb.rb @@ -0,0 +1,67 @@ +require 'ruby-debug-ide/attach/native_debugger' + +class LLDB < NativeDebugger + + def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + super(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + end + + def set_flags + + end + + def update_threads + @process_threads = [] + info_threads = (execute 'thread list').split("\n") + info_threads.each do |thread_info| + next unless thread_info =~ /[\s*]*thread\s#\d+.*/ + is_main = thread_info[0] == '*' + thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i + thread = ProcessThread.new(thread_num, is_main, thread_info, self) + if thread.is_main + @main_thread = thread + end + @process_threads << thread + end + @process_threads + end + + def check_already_under_debug + threads = execute 'thread list' + threads =~ /ruby-debug-ide/ + end + + def switch_to_thread(thread_num) + execute "thread select #{thread_num}" + end + + def call_start_attach + super() + execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)" + execute 'expr (int) start_attach()' + set_tbreak(@tbreak) + end + + def print_delimiter + @pipe.puts "script print \"#{@delimiter}\"" + end + + def check_delimiter(line) + line =~ /#{@delimiter}$/ + end + + def load_debugger + execute "expr (VALUE) #{@eval_string}" + end + + def to_s + LLDB.to_s + end + + class << self + def to_s + 'lldb' + end + end + +end diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb new file mode 100644 index 0000000..d48ed1e --- /dev/null +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -0,0 +1,129 @@ +class NativeDebugger + + attr_reader :pid, :main_thread, :process_threads, :pipe + + # @param executable -- path to ruby interpreter + # @param pid -- pid of process you want to debug + # @param flags -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit) + def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv) + @pid = pid + @delimiter = '__OUTPUT_FINISHED__' # for getting response + @tbreak = '__func_to_set_breakpoint_at' + @main_thread = nil + @process_threads = nil + debase_path = gems_to_include.select {|gem_path| gem_path =~ /debase/} + if debase_path.size == 0 + raise 'No debase gem found.' + end + @path_to_attach = find_attach_lib(debase_path[0]) + + @gems_to_include = '["' + gems_to_include * '", "' + '"]' + @debugger_loader_path = debugger_loader_path + @argv = argv + + @eval_string = "rb_eval_string_protect(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" + + launch_string = "#{self} #{executable} #{flags}" + @pipe = IO.popen(launch_string, 'r+') + $stdout.puts "executed '#{launch_string}'" + end + + def find_attach_lib(debase_path) + attach_lib = debase_path + '/attach' + known_extensions = %w(.so .bundle .dll) + known_extensions.each do |ext| + if File.file?(attach_lib + ext) + return attach_lib + ext + end + end + + raise 'Could not find attach library' + end + + def attach_to_process + execute "attach #{@pid}" + end + + def execute(command) + @pipe.puts command + $stdout.puts "executed `#{command}` command inside #{self}." + if command == 'q' + return '' + end + get_response + end + + def get_response + # we need this hack to understand that debugger gave us all output from last executed command + print_delimiter + + content = '' + loop do + line = @pipe.readline + break if check_delimiter(line) + DebugPrinter.print_debug('respond line: ' + line) + next if line =~ /\(lldb\)/ # lldb repeats your input to its output + content += line + end + + content + end + + def update_threads + + end + + def check_already_under_debug + + end + + def print_delimiter + + end + + def check_delimiter(line) + + end + + def switch_to_thread + + end + + def set_tbreak(str) + execute "tbreak #{str}" + end + + def continue + $stdout.puts 'continuing' + @pipe.puts 'c' + loop do + line = @pipe.readline + break if line =~ /#{Regexp.escape(@tbreak)}/ + end + get_response + end + + def call_start_attach + raise 'No main thread found. Did you forget to call `update_threads`?' if @main_thread == nil + @main_thread.switch + end + + def wait_line_event + call_start_attach + continue + end + + def load_debugger + + end + + def exit + execute 'q' + @pipe.close + end + + def to_s + 'native_debugger' + end + +end diff --git a/lib/ruby-debug-ide/attach/process_thread.rb b/lib/ruby-debug-ide/attach/process_thread.rb new file mode 100644 index 0000000..cee7ea7 --- /dev/null +++ b/lib/ruby-debug-ide/attach/process_thread.rb @@ -0,0 +1,54 @@ +require 'ruby-debug-ide/attach/native_debugger' + +class ProcessThread + + attr_reader :thread_num, :is_main, :thread_info, :last_bt + + def initialize(thread_num, is_main, thread_info, native_debugger) + @thread_num = thread_num + @is_main = is_main + @native_debugger = native_debugger + @thread_info = thread_info + @last_bt = nil + end + + def switch + @native_debugger.switch_to_thread(thread_num) + end + + def finish + @native_debugger.execute 'finish' + end + + def get_bt + @last_bt = @native_debugger.execute 'bt' + end + + def any_caller_match(bt, pattern) + bt =~ /#{pattern}/ + end + + def is_inside_malloc(bt = get_bt) + if any_caller_match(bt, '(malloc)') + $stderr.puts "process #{@native_debugger.pid} is currently inside malloc." + true + else + false + end + end + + def is_inside_gc(bt = get_bt) + if any_caller_match(bt, '(gc\.c)') + $stderr.puts "process #{@native_debugger.pid} is currently in garbage collection phase." + true + else + false + end + end + + def need_finish_frame + bt = get_bt + is_inside_malloc(bt) || is_inside_gc(bt) + end + +end diff --git a/lib/ruby-debug-ide/attach/util.rb b/lib/ruby-debug-ide/attach/util.rb new file mode 100644 index 0000000..035933c --- /dev/null +++ b/lib/ruby-debug-ide/attach/util.rb @@ -0,0 +1,35 @@ +require 'ruby-debug-ide/attach/lldb' +require 'ruby-debug-ide/attach/gdb' + +def command_exists(command) + checking_command = "checking command #{command} for existence\n" + `command -v #{command} >/dev/null 2>&1 || { exit 1; }` + if $?.exitstatus != 0 + DebugPrinter.print_debug("#{checking_command}command does not exist.") + else + DebugPrinter.print_debug("#{checking_command}command does exist.") + end + $?.exitstatus == 0 +end + +def choose_debugger(ruby_path, pid, gems_to_include, debugger_loader_path, argv) + if command_exists(LLDB.to_s) + debugger = LLDB.new(ruby_path, pid, '--no-lldbinit', gems_to_include, debugger_loader_path, argv) + elsif command_exists(GDB.to_s) + debugger = GDB.new(ruby_path, pid, '-nh -nx', gems_to_include, debugger_loader_path, argv) + else + raise 'Neither gdb nor lldb was found. Aborting.' + end + + trap('INT') do + unless debugger.pipe.closed? + $stderr.puts "backtraces for threads:\n\n" + debugger.process_threads.each do |thread| + $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" + end + end + exit! + end + + debugger +end From fa117ee53e8034629deb3e0e1aadb20313f1fb7f Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 10 Oct 2016 18:40:18 +0300 Subject: [PATCH 175/302] More debug output --- lib/ruby-debug-ide/attach/native_debugger.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb index d48ed1e..4d9df48 100644 --- a/lib/ruby-debug-ide/attach/native_debugger.rb +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -60,8 +60,8 @@ def get_response content = '' loop do line = @pipe.readline - break if check_delimiter(line) DebugPrinter.print_debug('respond line: ' + line) + break if check_delimiter(line) next if line =~ /\(lldb\)/ # lldb repeats your input to its output content += line end @@ -98,6 +98,7 @@ def continue @pipe.puts 'c' loop do line = @pipe.readline + DebugPrinter.print_debug('respond line: ' + line) break if line =~ /#{Regexp.escape(@tbreak)}/ end get_response From 327fd704fe9bfd2afcfc2444cad5607df4ad835f Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 17 Oct 2016 15:18:58 +0300 Subject: [PATCH 176/302] More lldb-like breakpoint setting --- lib/ruby-debug-ide/attach/gdb.rb | 6 +++++- lib/ruby-debug-ide/attach/lldb.rb | 6 +++++- lib/ruby-debug-ide/attach/native_debugger.rb | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/attach/gdb.rb b/lib/ruby-debug-ide/attach/gdb.rb index a507880..1214816 100644 --- a/lib/ruby-debug-ide/attach/gdb.rb +++ b/lib/ruby-debug-ide/attach/gdb.rb @@ -37,11 +37,15 @@ def switch_to_thread(thread_num) execute "thread #{thread_num}" end + def set_break(str) + execute "tbreak #{str}" + end + def call_start_attach super() execute "call dlopen(\"#{@path_to_attach}\", 2)" execute 'call start_attach()' - set_tbreak(@tbreak) + set_break(@tbreak) end def print_delimiter diff --git a/lib/ruby-debug-ide/attach/lldb.rb b/lib/ruby-debug-ide/attach/lldb.rb index 87245df..5d301d2 100644 --- a/lib/ruby-debug-ide/attach/lldb.rb +++ b/lib/ruby-debug-ide/attach/lldb.rb @@ -35,11 +35,15 @@ def switch_to_thread(thread_num) execute "thread select #{thread_num}" end + def set_break(str) + execute "breakpoint set --shlib #{@path_to_attach} --name #{str}" + end + def call_start_attach super() execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)" execute 'expr (int) start_attach()' - set_tbreak(@tbreak) + set_break(@tbreak) end def print_delimiter diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb index 4d9df48..852d5a4 100644 --- a/lib/ruby-debug-ide/attach/native_debugger.rb +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -89,8 +89,8 @@ def switch_to_thread end - def set_tbreak(str) - execute "tbreak #{str}" + def set_break(str) + end def continue From 68e87533a2268cf0bccc31f3b164e8125caee507 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 17 Oct 2016 15:22:35 +0300 Subject: [PATCH 177/302] Proper extension added --- lib/ruby-debug-ide/attach/native_debugger.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb index 852d5a4..cda6876 100644 --- a/lib/ruby-debug-ide/attach/native_debugger.rb +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -30,7 +30,7 @@ def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, ar def find_attach_lib(debase_path) attach_lib = debase_path + '/attach' - known_extensions = %w(.so .bundle .dll) + known_extensions = %w(.so .bundle .dll .dylib) known_extensions.each do |ext| if File.file?(attach_lib + ext) return attach_lib + ext From dc009872a7073c608ce1e98a9f55068248a4e548 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Mon, 17 Oct 2016 15:28:11 +0300 Subject: [PATCH 178/302] C extension for attach already moved to debase gem --- ext/Makefile | 10 ---------- ext/attach.c | 29 ----------------------------- ext/attach.h | 9 --------- 3 files changed, 48 deletions(-) delete mode 100644 ext/Makefile delete mode 100644 ext/attach.c delete mode 100644 ext/attach.h diff --git a/ext/Makefile b/ext/Makefile deleted file mode 100644 index 6c52c90..0000000 --- a/ext/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -all: libAttach.so - -libAttach.so: libAttach.o - gcc -shared -o libAttach.so libAttach.o - -libAttach.o: attach.c - gcc -Wall -g -fPIC -c -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0 -I/home/equi/.rvm/rubies/ruby-2.3.1/include/ruby-2.3.0/x86_64-linux/ attach.c -o libAttach.o - -clean: - rm libAttach.* diff --git a/ext/attach.c b/ext/attach.c deleted file mode 100644 index d4d4dbe..0000000 --- a/ext/attach.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "attach.h" - -static void -__func_to_set_breakpoint_at() -{ -} - -static void -__catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass) -{ - (void)sizeof(evflag); - (void)sizeof(self); - (void)sizeof(mid); - (void)sizeof(klass); - - rb_remove_event_hook(__catch_line_event); - if (rb_during_gc()) - return; - __func_to_set_breakpoint_at(); -} - -int -start_attach() -{ - if (rb_during_gc()) - return 1; - rb_add_event_hook(__catch_line_event, RUBY_EVENT_LINE, (VALUE) NULL); - return 0; -} diff --git a/ext/attach.h b/ext/attach.h deleted file mode 100644 index 9c98192..0000000 --- a/ext/attach.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ATTACH_H__ -#define __ATTACH_H__ - -#include -#include - -int start_attach(); - -#endif //__ATTACH_H__ \ No newline at end of file From 17e92ecfd75f3f4c0829f5371705ad2b1e25afc2 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Fri, 28 Oct 2016 01:39:23 +0300 Subject: [PATCH 179/302] Changed `start_attach` function name in debase. Added wrapper function `debase_rb_eval` in debase --- lib/ruby-debug-ide/attach/gdb.rb | 2 +- lib/ruby-debug-ide/attach/lldb.rb | 4 ++-- lib/ruby-debug-ide/attach/native_debugger.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/attach/gdb.rb b/lib/ruby-debug-ide/attach/gdb.rb index 1214816..bf9085c 100644 --- a/lib/ruby-debug-ide/attach/gdb.rb +++ b/lib/ruby-debug-ide/attach/gdb.rb @@ -44,7 +44,7 @@ def set_break(str) def call_start_attach super() execute "call dlopen(\"#{@path_to_attach}\", 2)" - execute 'call start_attach()' + execute 'call debase_start_attach()' set_break(@tbreak) end diff --git a/lib/ruby-debug-ide/attach/lldb.rb b/lib/ruby-debug-ide/attach/lldb.rb index 5d301d2..b9bdc31 100644 --- a/lib/ruby-debug-ide/attach/lldb.rb +++ b/lib/ruby-debug-ide/attach/lldb.rb @@ -42,7 +42,7 @@ def set_break(str) def call_start_attach super() execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)" - execute 'expr (int) start_attach()' + execute 'expr (int) debase_start_attach()' set_break(@tbreak) end @@ -55,7 +55,7 @@ def check_delimiter(line) end def load_debugger - execute "expr (VALUE) #{@eval_string}" + execute "expr (void) #{@eval_string}" end def to_s diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb index cda6876..87eebc9 100644 --- a/lib/ruby-debug-ide/attach/native_debugger.rb +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -21,7 +21,7 @@ def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, ar @debugger_loader_path = debugger_loader_path @argv = argv - @eval_string = "rb_eval_string_protect(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" + @eval_string = "debase_rb_eval(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" launch_string = "#{self} #{executable} #{flags}" @pipe = IO.popen(launch_string, 'r+') From e22c174962e9c533cf2c0554c33504781189ddfd Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 31 Oct 2016 15:01:04 +0300 Subject: [PATCH 180/302] fix argument count for debase_rb_eval --- lib/ruby-debug-ide/attach/native_debugger.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb index 87eebc9..e0a8c1c 100644 --- a/lib/ruby-debug-ide/attach/native_debugger.rb +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -21,7 +21,7 @@ def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, ar @debugger_loader_path = debugger_loader_path @argv = argv - @eval_string = "debase_rb_eval(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\", (int *)0)" + @eval_string = "debase_rb_eval(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\")" launch_string = "#{self} #{executable} #{flags}" @pipe = IO.popen(launch_string, 'r+') From 2dc448021ab62cc47beaab34bf648224f698db73 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 31 Oct 2016 15:01:22 +0300 Subject: [PATCH 181/302] bump --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 48c578c..8b224d7 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta2' + IDE_VERSION='0.6.1.beta3' end From 1e091ce77eecebe9ee92ef4490beffb9b708dbc3 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Wed, 9 Nov 2016 13:44:59 +0300 Subject: [PATCH 182/302] We should use stdout to print greeting message in attach mode because gksudo swallows stderr. --- bin/gdb_wrapper | 2 +- lib/ruby-debug-ide.rb | 2 +- lib/ruby-debug-ide/greeter.rb | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 905e741..56eb0d8 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -72,7 +72,7 @@ options.gems_to_include.each do |gem_path| end require 'ruby-debug-ide/greeter' -Debugger::print_greeting_msg(nil, nil) +Debugger::print_greeting_msg($stdout, nil, nil) require 'ruby-debug-ide/attach/util' require 'ruby-debug-ide/attach/native_debugger' diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 30fc079..d100fe5 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -111,7 +111,7 @@ def start_control(host, port, notify_dispatcher) # "localhost" and nil have problems on some systems. host ||= '127.0.0.1' server = TCPServer.new(host, port) - print_greeting_msg(host, port) + print_greeting_msg($stderr, host, port) notify_dispatcher(port) if notify_dispatcher while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug diff --git a/lib/ruby-debug-ide/greeter.rb b/lib/ruby-debug-ide/greeter.rb index a851913..df9b042 100644 --- a/lib/ruby-debug-ide/greeter.rb +++ b/lib/ruby-debug-ide/greeter.rb @@ -10,7 +10,7 @@ module Debugger class << self - def print_greeting_msg(host, port) + def print_greeting_msg(stream, host, port) base_gem_name = if defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0' 'ruby-debug-base' elsif RUBY_VERSION < '2.0.0' @@ -33,7 +33,7 @@ def print_greeting_msg(host, port) msg = "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{base_gem_name} #{VERSION}, file filtering is #{file_filtering_support})" + listens_on - $stderr.printf msg + stream.printf msg end end From 7e69ab7ad8941b899a6605e31dfc32ccc333477f Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Wed, 9 Nov 2016 15:31:15 +0300 Subject: [PATCH 183/302] refactoring -- moved trap initialization to main --- bin/gdb_wrapper | 11 +++++++++++ lib/ruby-debug-ide/attach/util.rb | 10 ---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 56eb0d8..0f0709d 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -79,6 +79,17 @@ require 'ruby-debug-ide/attach/native_debugger' require 'ruby-debug-ide/attach/process_thread' debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv) + +trap('INT') do + unless debugger.pipe.closed? + $stderr.puts "backtraces for threads:\n\n" + debugger.process_threads.each do |thread| + $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" + end + end + exit! +end + debugger.attach_to_process debugger.set_flags diff --git a/lib/ruby-debug-ide/attach/util.rb b/lib/ruby-debug-ide/attach/util.rb index 035933c..faa8478 100644 --- a/lib/ruby-debug-ide/attach/util.rb +++ b/lib/ruby-debug-ide/attach/util.rb @@ -21,15 +21,5 @@ def choose_debugger(ruby_path, pid, gems_to_include, debugger_loader_path, argv) raise 'Neither gdb nor lldb was found. Aborting.' end - trap('INT') do - unless debugger.pipe.closed? - $stderr.puts "backtraces for threads:\n\n" - debugger.process_threads.each do |thread| - $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" - end - end - exit! - end - debugger end From e1d1d363ae4c2338726a1acaa3aafe1abaadbe82 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Wed, 9 Nov 2016 15:40:01 +0300 Subject: [PATCH 184/302] better handling of int signal. --- bin/gdb_wrapper | 10 +++++++--- lib/ruby-debug-ide/attach/native_debugger.rb | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 0f0709d..c89bd8d 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -81,11 +81,15 @@ require 'ruby-debug-ide/attach/process_thread' debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv) trap('INT') do - unless debugger.pipe.closed? + unless debugger.exited? $stderr.puts "backtraces for threads:\n\n" - debugger.process_threads.each do |thread| - $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" + process_threads = debugger.process_threads + if process_threads + process_threads.each do |thread| + $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" + end end + debugger.exit end exit! end diff --git a/lib/ruby-debug-ide/attach/native_debugger.rb b/lib/ruby-debug-ide/attach/native_debugger.rb index e0a8c1c..05ea9d9 100644 --- a/lib/ruby-debug-ide/attach/native_debugger.rb +++ b/lib/ruby-debug-ide/attach/native_debugger.rb @@ -118,8 +118,11 @@ def load_debugger end + def exited? + @pipe.closed? + end + def exit - execute 'q' @pipe.close end From 279e28ec8e0d0be60d64978a27ab9af686242ee1 Mon Sep 17 00:00:00 2001 From: equivalence1 Date: Thu, 15 Dec 2016 03:45:48 +0300 Subject: [PATCH 185/302] exec monkey patch fix --- bin/rdebug-ide | 3 +- lib/ruby-debug-ide/commands/control.rb | 2 +- lib/ruby-debug-ide/multiprocess.rb | 22 ++++++++++++-- lib/ruby-debug-ide/multiprocess/pre_child.rb | 2 -- lib/ruby-debug-ide/multiprocess/unmonkey.rb | 31 ++++++++++++++++++++ 5 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 lib/ruby-debug-ide/multiprocess/unmonkey.rb diff --git a/bin/rdebug-ide b/bin/rdebug-ide index dced3a7..69b2c60 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -117,6 +117,7 @@ if options.dispatcher_port != -1 else require_relative '../lib/ruby-debug-ide/multiprocess' end + Debugger::MultiProcess.do_monkey ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB'] old_opts = ENV['RUBYOPT'] || '' @@ -140,8 +141,6 @@ Debugger.evaluation_timeout = options.evaluation_timeout Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions -Debugger.attached = true - if options.attach_mode if Debugger::FRONT_END == "debase" Debugger.init_variables diff --git a/lib/ruby-debug-ide/commands/control.rb b/lib/ruby-debug-ide/commands/control.rb index bc09bda..6fd030f 100644 --- a/lib/ruby-debug-ide/commands/control.rb +++ b/lib/ruby-debug-ide/commands/control.rb @@ -136,9 +136,9 @@ def regexp end def execute - Debugger.attached = false Debugger.stop Debugger.interface.close + Debugger::MultiProcess.undo_monkey Debugger.control_thread = nil Thread.current.exit #@control_thread is a current thread end diff --git a/lib/ruby-debug-ide/multiprocess.rb b/lib/ruby-debug-ide/multiprocess.rb index 1366327..4342ef7 100644 --- a/lib/ruby-debug-ide/multiprocess.rb +++ b/lib/ruby-debug-ide/multiprocess.rb @@ -1,7 +1,23 @@ -if RUBY_VERSION < "1.9" +if RUBY_VERSION < '1.9' require 'ruby-debug-ide/multiprocess/pre_child' - require 'ruby-debug-ide/multiprocess/monkey' else require_relative 'multiprocess/pre_child' - require_relative 'multiprocess/monkey' +end + +module Debugger + module MultiProcess + class << self + def do_monkey + load File.expand_path(File.dirname(__FILE__) + '/multiprocess/monkey.rb') + end + + def undo_monkey + if ENV['IDE_PROCESS_DISPATCHER'] + load File.expand_path(File.dirname(__FILE__) + '/multiprocess/unmonkey.rb') + ruby_opts = ENV['RUBYOPT'].split(' ') + ENV['RUBYOPT'] = ruby_opts.keep_if {|opt| !opt.end_with?('ruby-debug-ide/multiprocess/starter')}.join(' ') + end + end + end + end end \ No newline at end of file diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 7a2f4fc..eb96242 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -2,8 +2,6 @@ module Debugger module MultiProcess class << self def pre_child(options = nil) - return unless Debugger.attached - require 'socket' require 'ostruct' diff --git a/lib/ruby-debug-ide/multiprocess/unmonkey.rb b/lib/ruby-debug-ide/multiprocess/unmonkey.rb new file mode 100644 index 0000000..82e6c6e --- /dev/null +++ b/lib/ruby-debug-ide/multiprocess/unmonkey.rb @@ -0,0 +1,31 @@ +module Debugger + module MultiProcess + def self.restore_fork + %Q{ + alias fork pre_debugger_fork + } + end + + def self.restore_exec + %Q{ + alias exec pre_debugger_exec + } + end + end +end + +module Kernel + class << self + module_eval Debugger::MultiProcess.restore_fork + module_eval Debugger::MultiProcess.restore_exec + end + module_eval Debugger::MultiProcess.restore_fork + module_eval Debugger::MultiProcess.restore_exec +end + +module Process + class << self + module_eval Debugger::MultiProcess.restore_fork + module_eval Debugger::MultiProcess.restore_exec + end +end \ No newline at end of file From b0fddb600a50311dca452c10097aeadc174b93b3 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 22 Dec 2016 14:18:46 +0300 Subject: [PATCH 186/302] bump gem version --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 8b224d7..bda7cbb 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta3' + IDE_VERSION='0.6.1.beta4' end From 1fc391126a64239995a73f3e91b17cbbac12190e Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 9 Jun 2017 18:22:42 +0300 Subject: [PATCH 187/302] uncoding for >2.0 fixed --- lib/ruby-debug-ide/command.rb | 1 + lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 1839af2..4d4f732 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -118,6 +118,7 @@ def timeout(sec) def debug_eval(str, b = get_binding) begin str = str.to_s + str.force_encoding('UTF-8') if(RUBY_VERSION > 2.0) to_inspect = Command.unescape_incoming(str) max_time = Debugger.evaluation_timeout @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index bda7cbb..560323f 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta4' + IDE_VERSION='0.6.1.beta5' end From e5f34cde272ec156c7f2c0d283778c1656b9c89f Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Wed, 5 Jul 2017 11:36:17 +0300 Subject: [PATCH 188/302] zeus deadlock fix --- lib/ruby-debug-ide/multiprocess/starter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ruby-debug-ide/multiprocess/starter.rb b/lib/ruby-debug-ide/multiprocess/starter.rb index f8435e4..5e312f8 100644 --- a/lib/ruby-debug-ide/multiprocess/starter.rb +++ b/lib/ruby-debug-ide/multiprocess/starter.rb @@ -6,5 +6,6 @@ end require 'ruby-debug-ide' require 'ruby-debug-ide/multiprocess' + Debugger::MultiProcess::do_monkey Debugger::MultiProcess::pre_child end \ No newline at end of file From 50b61a4d414cae63841aa6daaa77fc63fa583396 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Wed, 5 Jul 2017 11:46:19 +0300 Subject: [PATCH 189/302] cleanup --- lib/ruby-debug-ide/command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 4d4f732..5f099be 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -118,7 +118,7 @@ def timeout(sec) def debug_eval(str, b = get_binding) begin str = str.to_s - str.force_encoding('UTF-8') if(RUBY_VERSION > 2.0) + str.force_encoding('UTF-8') if(RUBY_VERSION > '2.0') to_inspect = Command.unescape_incoming(str) max_time = Debugger.evaluation_timeout @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time) From 03a6101dfba0e36e78729aee86aba94077df2902 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Tue, 25 Jul 2017 15:22:43 +0300 Subject: [PATCH 190/302] inspect memory limit fix (#100) Add time and memory limit checks for `inspect` and `to_s` Some automatic UI-related queries to the debugger may cause OOM or hangs in the case of recursive or just very large data structures being inspected. This commit adds the possibility (enabled by default) to add time and memory limits for dangerous calls to objects from a user codebase. Related: RUBY-18275, RUBY-18121, RUBY-19520. Commits reviewed and squashed: * inspect memory limit * cleanup * Option to disable memory check is added * disable memory limit in the same option * cleanup: formating fix, rename variable, rewrite on "compact = if (...)" * fixed exeption message * memory limit logging added * debug output deleted * print_msg -> print_debug * object_id deleted from the exeption message * Fixes according to the review * timelimit for inspect evaluation added * The handler is called with a probability of 25% * cleanup * inspect_with_alloc_control -> exec_with_... and heuristic break for variable inspect * fixes according to reiew --- bin/rdebug-ide | 11 +++++ lib/ruby-debug-ide/xml_printer.rb | 81 +++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 69b2c60..34d563d 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -36,6 +36,17 @@ Usage: rdebug-ide is supposed to be called from RDT, NetBeans, RubyMine, or EOB opts.separator "" opts.separator "Options:" + + ENV['DEBUGGER_MEMORY_LIMIT'] = '10' + opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit| + ENV['DEBUGGER_MEMORY_LIMIT'] = limit + end + + ENV['INSPECT_TIME_LIMIT'] = '100' + opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit| + ENV['INSPECT_TIME_LIMIT'] = limit + end + opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 00f08b5..0b0e607 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -1,9 +1,30 @@ require 'stringio' require 'cgi' require 'monitor' +require 'objspace' module Debugger + class MemoryLimitError < StandardError + attr_reader :message + attr_reader :backtrace + + def initialize(message, backtrace = '') + @message = message + @backtrace = backtrace + end + end + + class TimeLimitError < StandardError + attr_reader :message + attr_reader :backtrace + + def initialize(message, backtrace = '') + @message = message + @backtrace = backtrace + end + end + class XmlPrinter # :nodoc: class ExceptionProxy instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$|^instance_variables$|^instance_eval$)/ } @@ -137,7 +158,45 @@ def print_string(string) print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding') end end - + + def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, return_message_if_overflow) + curr_thread = Thread.current + result = nil + inspect_thread = DebugThread.start { + start_alloc_size = ObjectSpace.memsize_of_all + start_time = Time.now.to_f + + trace = TracePoint.new(:c_call, :call) do |tp| + + if(rand > 0.75) + curr_alloc_size = ObjectSpace.memsize_of_all + curr_time = Time.now.to_f + + if((curr_time - start_time) * 1e3 > time_limit) + curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", "#{caller.map{|l| "\t#{l}"}.join("\n")}") + inspect_thread.kill + end + + start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) + + if(curr_alloc_size - start_alloc_size > 1e6 * memory_limit) + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map{|l| "\t#{l}"}.join("\n")}") + inspect_thread.kill + end + end + end.enable { + result = value.send exec_method + } + } + inspect_thread.join + inspect_thread.kill + return result + rescue MemoryLimitError, TimeLimitError => e + print_debug(e.message + "\n" + e.backtrace) + + return return_message_if_overflow ? e.message : nil + end + def print_variable(name, value, kind) name = name.to_s if value.nil? @@ -157,7 +216,13 @@ def print_variable(name, value, kind) value_str = value else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" + + value_str = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) + value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" + else + exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, false) || 'nil' rescue "<#to_s method raised exception: #{$!}>" + end + unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end @@ -382,11 +447,17 @@ def max_compact_name_size def compact_array_str(value) slice = value[0..10] - compact = slice.inspect - if value.size != slice.size + + compact = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) + slice.inspect + else + exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, true) + end + + if compact && value.size != slice.size compact[0..compact.size-2] + ", ...]" end - compact + compact end def compact_hash_str(value) From da5c61935fad57810ebabb77f8c1619c70f5ca7b Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 1 Aug 2017 16:06:47 +0300 Subject: [PATCH 191/302] set tl and ml for calculating self.to_s --- lib/ruby-debug-ide/commands/variables.rb | 3 ++- lib/ruby-debug-ide/xml_printer.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index cc8d935..ccc5841 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -129,7 +129,8 @@ def execute locals = @state.context.frame_locals(@state.frame_pos) _self = @state.context.frame_self(@state.frame_pos) begin - locals['self'] = _self unless "main" == _self.to_s + _self_str = exec_with_allocation_control(_self, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, false) + locals['self'] = _self unless "main" == _self_str rescue => ex locals['self'] = "" $stderr << "Cannot evaluate self\n#{ex.class.name}: #{ex.message}\n #{ex.backtrace.join("\n ")}" diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 0b0e607..d5fd24b 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -220,7 +220,7 @@ def print_variable(name, value, kind) value_str = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" else - exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, false) || 'nil' rescue "<#to_s method raised exception: #{$!}>" + exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, true) || 'nil' rescue "<#to_s method raised exception: #{$!}>" end unless value_str.is_a?(String) From f821ffbfd6df32c2d34cf48b0b77ca66fc03045e Mon Sep 17 00:00:00 2001 From: viuginick Date: Thu, 3 Aug 2017 23:44:24 +0300 Subject: [PATCH 192/302] refactor xml_printer --- lib/ruby-debug-ide/xml_printer.rb | 178 +++++++++++++++--------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index d5fd24b..0334266 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -5,7 +5,7 @@ module Debugger - class MemoryLimitError < StandardError + class MemoryLimitError < StandardError attr_reader :message attr_reader :backtrace @@ -13,9 +13,9 @@ def initialize(message, backtrace = '') @message = message @backtrace = backtrace end - end + end - class TimeLimitError < StandardError + class TimeLimitError < StandardError attr_reader :message attr_reader :backtrace @@ -23,11 +23,11 @@ def initialize(message, backtrace = '') @message = message @backtrace = backtrace end - end + end class XmlPrinter # :nodoc: class ExceptionProxy - instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$|^instance_variables$|^instance_eval$)/ } + instance_methods.each {|m| undef_method m unless m =~ /(^__|^send$|^object_id$|^instance_variables$|^instance_eval$)/} def initialize(exception) @exception = exception @@ -35,9 +35,9 @@ def initialize(exception) @backtrace = Debugger.cleanup_backtrace(exception.backtrace) end - private - def method_missing(called, *args, &block) - @exception.__send__(called, *args, &block) + private + def method_missing(called, *args, &block) + @exception.__send__(called, *args, &block) end end @@ -52,15 +52,15 @@ def #{mname}(*args, &block) end end } - end + end @@monitor = Monitor.new attr_accessor :interface - + def initialize(interface) @interface = interface end - + def print_msg(*args) msg, *args = args xml_message = CGI.escapeHTML(msg % args) @@ -83,7 +83,7 @@ def print_error(*args) print CGI.escapeHTML(msg % args) end end - + def print_frames(context, current_frame_id) print_element("frames") do (0...context.stack_size).each do |id| @@ -91,18 +91,18 @@ def print_frames(context, current_frame_id) end end end - + def print_current_frame(frame_pos) print_debug "Selected frame no #{frame_pos}" end - + def print_frame(context, frame_id, current_frame_id) # idx + 1: one-based numbering as classic-debugger file = context.frame_file(frame_id) print "", - frame_id + 1, CGI.escapeHTML(File.expand_path(file)), context.frame_line(frame_id) + frame_id + 1, CGI.escapeHTML(File.expand_path(file)), context.frame_line(frame_id) end - + def print_contexts(contexts) print_element("threads") do contexts.each do |c| @@ -110,11 +110,11 @@ def print_contexts(contexts) end end end - + def print_context(context) print "", context.thnum, context.thread.status, Process.pid end - + def print_variables(vars, kind) print_element("variables") do # print self at top position @@ -124,26 +124,26 @@ def print_variables(vars, kind) end end end - + def print_array(array) print_element("variables") do - index = 0 - array.each { |e| - print_variable('[' + index.to_s + ']', e, 'instance') - index += 1 + index = 0 + array.each {|e| + print_variable('[' + index.to_s + ']', e, 'instance') + index += 1 } end end - + def print_hash(hash) print_element("variables") do - hash.keys.each { | k | + hash.keys.each {|k| if k.class.name == "String" name = '\'' + k + '\'' else name = k.to_s end - print_variable(name, hash[k], 'instance') + print_variable(name, hash[k], 'instance') } end end @@ -155,7 +155,7 @@ def print_string(string) InspectCommand.reference_result(bytes) print_variable('bytes', bytes, 'instance') end - print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding') + print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding') end end @@ -165,22 +165,22 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, r inspect_thread = DebugThread.start { start_alloc_size = ObjectSpace.memsize_of_all start_time = Time.now.to_f - + trace = TracePoint.new(:c_call, :call) do |tp| - - if(rand > 0.75) + + if (rand > 0.75) curr_alloc_size = ObjectSpace.memsize_of_all curr_time = Time.now.to_f - - if((curr_time - start_time) * 1e3 > time_limit) - curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", "#{caller.map{|l| "\t#{l}"}.join("\n")}") + + if ((curr_time - start_time) * 1e3 > time_limit) + curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", "#{caller.map {|l| "\t#{l}"}.join("\n")}") inspect_thread.kill end start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) - - if(curr_alloc_size - start_alloc_size > 1e6 * memory_limit) - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map{|l| "\t#{l}"}.join("\n")}") + + if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit) + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map {|l| "\t#{l}"}.join("\n")}") inspect_thread.kill end end @@ -193,7 +193,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, r return result rescue MemoryLimitError, TimeLimitError => e print_debug(e.message + "\n" + e.backtrace) - + return return_message_if_overflow ? e.message : nil end @@ -206,7 +206,7 @@ def print_variable(name, value, kind) if value.is_a?(Array) || value.is_a?(Hash) has_children = !value.empty? if has_children - size = value.size + size = value.size value_str = "#{value.class} (#{value.size} element#{size > 1 ? "s" : "" })" else value_str = "Empty #{value.class}" @@ -214,33 +214,33 @@ def print_variable(name, value, kind) elsif value.is_a?(String) has_children = value.respond_to?('bytes') || value.respond_to?('encoding') value_str = value - else + else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - + value_str = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) - value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" - else - exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, true) || 'nil' rescue "<#to_s method raised exception: #{$!}>" - end - + value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" + else + exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, true) || 'nil' rescue "<#to_s method raised exception: #{$!}>" + end + unless value_str.is_a?(String) - value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." + value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end end if value_str.respond_to?('encode') # noinspection RubyEmptyRescueBlockInspection begin - value_str = value_str.encode("UTF-8") + value_str = value_str.encode("UTF-8") rescue end end value_str = handle_binary_data(value_str) escaped_value_str = CGI.escapeHTML(value_str) print("", - CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, - build_value_attr(escaped_value_str), value.class, - has_children, value.respond_to?(:object_id) ? value.object_id : value.id) + CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, + build_value_attr(escaped_value_str), value.class, + has_children, value.respond_to?(:object_id) ? value.object_id : value.id) print("", escaped_value_str) if Debugger.value_as_nested_element print('') rescue StandardError => e @@ -263,28 +263,28 @@ def print_file_filter_status(status) def print_breakpoints(breakpoints) print_element 'breakpoints' do - breakpoints.sort_by{|b| b.id }.each do |b| + breakpoints.sort_by {|b| b.id}.each do |b| print "", b.id, CGI.escapeHTML(b.source), b.pos.to_s end end end - + def print_breakpoint_added(b) print "", b.id, CGI.escapeHTML(b.source), b.pos end - + def print_breakpoint_deleted(b) print "", b.id end - + def print_breakpoint_enabled(b) print "", b.id end - + def print_breakpoint_disabled(b) print "", b.id end - + def print_contdition_set(bp_id) print "", bp_id end @@ -308,24 +308,24 @@ def print_expressions(exps) end end unless exps.empty? end - + def print_expression(exp, value, idx) print "", exp, value, idx end def print_expression_info(incomplete, prompt, indent) print "", - incomplete, CGI.escapeHTML(prompt), indent + incomplete, CGI.escapeHTML(prompt), indent end - + def print_eval(exp, value) - print "", CGI.escapeHTML(exp), value + print "", CGI.escapeHTML(exp), value end - + def print_pp(value) print value end - + def print_list(b, e, file, line) print "[%d, %d] in %s\n", b, e, file if (lines = Debugger.source_for(file)) @@ -342,7 +342,7 @@ def print_list(b, e, file, line) print "No source-file available for %s\n", file end end - + def print_methods(methods) print_element "methods" do methods.each do |method| @@ -350,31 +350,31 @@ def print_methods(methods) end end end - + # Events - + def print_breakpoint(_, breakpoint) print("", - CGI.escapeHTML(breakpoint.source), breakpoint.pos, Debugger.current_context.thnum) + CGI.escapeHTML(breakpoint.source), breakpoint.pos, Debugger.current_context.thnum) end - + def print_catchpoint(exception) context = Debugger.current_context - print("", - CGI.escapeHTML(context.frame_file(0)), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum) + print("", + CGI.escapeHTML(context.frame_file(0)), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum) end - + def print_trace(context, file, line) Debugger::print_debug "trace: location=\"%s:%s\", threadId=%d", file, line, context.thnum # TBD: do we want to clog fronend with the elements? There are tons of them. # print "", file, line, context.thnum end - + def print_at_line(context, file, line) print "", CGI.escapeHTML(File.expand_path(file)), line, context.thnum, context.stack_size end - + def print_exception(exception, _) print_element("variables") do proxy = ExceptionProxy.new(exception) @@ -382,21 +382,21 @@ def print_exception(exception, _) print_variable('error', proxy, 'exception') end rescue Exception - print "", - exception.class, CGI.escapeHTML(exception.to_s) + print "", + exception.class, CGI.escapeHTML(exception.to_s) end - + def print_inspect(eval_result) - print_element("variables") do + print_element("variables") do print_variable("eval_result", eval_result, 'local') end end - + def print_load_result(file, exception=nil) if exception - print("", file, exception.class, CGI.escapeHTML(exception.to_s)) + print("", file, exception.class, CGI.escapeHTML(exception.to_s)) else - print("", file) + print("", file) end end @@ -410,7 +410,7 @@ def print_element(name) end private - + def print(*params) Debugger::print_debug(*params) @interface.print(*params) @@ -446,28 +446,28 @@ def max_compact_name_size end def compact_array_str(value) - slice = value[0..10] + slice = value[0..10] compact = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) slice.inspect - else + else exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, true) - end - + end + if compact && value.size != slice.size compact[0..compact.size-2] + ", ...]" end - compact + compact end def compact_hash_str(value) - slice = value.sort_by { |k, _| k.to_s }[0..5] - compact = slice.map { |kv| "#{kv[0]}: #{handle_binary_data(kv[1])}" }.join(", ") + slice = value.sort_by {|k, _| k.to_s}[0..5] + compact = slice.map {|kv| "#{kv[0]}: #{handle_binary_data(kv[1])}"}.join(", ") "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end def build_compact_value_attr(value, value_str) - compact_value_str = build_compact_name(value, value_str) + compact_value_str = build_compact_name(value, value_str) compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\"" end @@ -493,7 +493,7 @@ def build_value_attr(escaped_value_str) protect m end end - + end end From 7e5f7f512150efcd59f54d66126bc529f022ef7d Mon Sep 17 00:00:00 2001 From: viuginick Date: Thu, 3 Aug 2017 23:47:52 +0300 Subject: [PATCH 193/302] refactoring: move jruby check into exec_with_allocation_method --- lib/ruby-debug-ide/xml_printer.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 0334266..de93202 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -160,6 +160,9 @@ def print_string(string) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, return_message_if_overflow) + if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) + return value.send exec_method + end curr_thread = Thread.current result = nil inspect_thread = DebugThread.start { @@ -217,11 +220,7 @@ def print_variable(name, value, kind) else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - value_str = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) - value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>" - else - exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, true) || 'nil' rescue "<#to_s method raised exception: #{$!}>" - end + value_str = exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, true) || 'nil' rescue "<#to_s method raised exception: #{$!}>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." @@ -448,11 +447,7 @@ def max_compact_name_size def compact_array_str(value) slice = value[0..10] - compact = if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) - slice.inspect - else - exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, true) - end + compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, true) if compact && value.size != slice.size compact[0..compact.size-2] + ", ...]" From f100c428f21a5207d06e893c70e57a812f18266e Mon Sep 17 00:00:00 2001 From: viuginick Date: Fri, 4 Aug 2017 00:14:15 +0300 Subject: [PATCH 194/302] refactoring: exception message type set by a lambda --- lib/ruby-debug-ide/xml_printer.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index de93202..7fdd803 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -5,6 +5,12 @@ module Debugger + module OverflowMessageType + NIL_MESSAGE = lambda {|e| nil} + EXCEPTION_MESSAGE = lambda {|e| e.message} + SPECIAL_SYMBOL_MESSAGE = lambda {|e| ''} + end + class MemoryLimitError < StandardError attr_reader :message attr_reader :backtrace @@ -159,7 +165,7 @@ def print_string(string) end end - def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, return_message_if_overflow) + def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) return value.send exec_method end @@ -197,7 +203,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, r rescue MemoryLimitError, TimeLimitError => e print_debug(e.message + "\n" + e.backtrace) - return return_message_if_overflow ? e.message : nil + return overflow_message_type.call(e) end def print_variable(name, value, kind) @@ -220,7 +226,7 @@ def print_variable(name, value, kind) else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - value_str = exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, true) || 'nil' rescue "<#to_s method raised exception: #{$!}>" + value_str = exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." @@ -447,7 +453,7 @@ def max_compact_name_size def compact_array_str(value) slice = value[0..10] - compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, true) + compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, OverflowMessageType::NIL_MESSAGE) if compact && value.size != slice.size compact[0..compact.size-2] + ", ...]" From da413e437ad46e3422675b0462ec00237bc6a941 Mon Sep 17 00:00:00 2001 From: viuginick Date: Fri, 4 Aug 2017 00:16:12 +0300 Subject: [PATCH 195/302] hix hashes with long keys/values --- lib/ruby-debug-ide/xml_printer.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 7fdd803..6130901 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -147,7 +147,7 @@ def print_hash(hash) if k.class.name == "String" name = '\'' + k + '\'' else - name = k.to_s + name = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) end print_variable(name, hash[k], 'instance') } @@ -462,8 +462,19 @@ def compact_array_str(value) end def compact_hash_str(value) - slice = value.sort_by {|k, _| k.to_s}[0..5] - compact = slice.map {|kv| "#{kv[0]}: #{handle_binary_data(kv[1])}"}.join(", ") + keys_strings = Hash.new + + slice = value.sort_by do |k, _| + keys_string = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) + keys_strings[k] = keys_string + keys_string + end[0..5] + + compact = slice.map do |kv| + key_string = keys_strings[kv[0]] + value_string = exec_with_allocation_control(kv[1], ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) + "#{key_string}: #{handle_binary_data(value_string)}" + end.join(", ") "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" end From 828f0d8685ff1082d4abe6f1eccb270028a4c334 Mon Sep 17 00:00:00 2001 From: viuginick Date: Fri, 4 Aug 2017 00:17:12 +0300 Subject: [PATCH 196/302] let timeout checks for jruby and little refactoring --- lib/ruby-debug-ide/xml_printer.rb | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 6130901..5e449d1 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -166,19 +166,20 @@ def print_string(string) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) + check_memory_limit = true if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) - return value.send exec_method + check_memory_limit = false end curr_thread = Thread.current result = nil inspect_thread = DebugThread.start { - start_alloc_size = ObjectSpace.memsize_of_all + + start_alloc_size = ObjectSpace.memsize_of_all if (check_memory_limit) start_time = Time.now.to_f trace = TracePoint.new(:c_call, :call) do |tp| if (rand > 0.75) - curr_alloc_size = ObjectSpace.memsize_of_all curr_time = Time.now.to_f if ((curr_time - start_time) * 1e3 > time_limit) @@ -186,11 +187,14 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o inspect_thread.kill end - start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) + if (check_memory_limit) + curr_alloc_size = ObjectSpace.memsize_of_all + start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) - if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit) - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map {|l| "\t#{l}"}.join("\n")}") - inspect_thread.kill + if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit) + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map {|l| "\t#{l}"}.join("\n")}") + inspect_thread.kill + end end end end.enable { @@ -309,7 +313,7 @@ def print_catchpoint_deleted(exception_class_name) def print_expressions(exps) print_element "expressions" do exps.each_with_index do |(exp, value), idx| - print_expression(exp, value, idx+1) + print_expression(exp, value, idx + 1) end end unless exps.empty? end @@ -335,11 +339,11 @@ def print_list(b, e, file, line) print "[%d, %d] in %s\n", b, e, file if (lines = Debugger.source_for(file)) b.upto(e) do |n| - if n > 0 && lines[n-1] + if n > 0 && lines[n - 1] if n == line - print "=> %d %s\n", n, lines[n-1].chomp + print "=> %d %s\n", n, lines[n - 1].chomp else - print " %d %s\n", n, lines[n-1].chomp + print " %d %s\n", n, lines[n - 1].chomp end end end @@ -397,7 +401,7 @@ def print_inspect(eval_result) end end - def print_load_result(file, exception=nil) + def print_load_result(file, exception = nil) if exception print("", file, exception.class, CGI.escapeHTML(exception.to_s)) else @@ -456,7 +460,7 @@ def compact_array_str(value) compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, OverflowMessageType::NIL_MESSAGE) if compact && value.size != slice.size - compact[0..compact.size-2] + ", ...]" + compact[0..compact.size - 2] + ", ...]" end compact end From 4333f10af68a30806a7d1b097452487d13b271ec Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Mon, 7 Aug 2017 12:35:11 +0300 Subject: [PATCH 197/302] improve attach mode to affect child processes (#108) This commit enables the attachment to the child processes of the original one. Useful for debugging application servers (see https://youtrack.jetbrains.com/issue/RUBY-19369) --- bin/gdb_wrapper | 48 +++---------- bin/rdebug-ide | 5 +- lib/ruby-debug-ide/attach/util.rb | 71 ++++++++++++++++++++ lib/ruby-debug-ide/multiprocess/pre_child.rb | 6 +- 4 files changed, 88 insertions(+), 42 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index c89bd8d..a439204 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -1,6 +1,7 @@ #!/usr/bin/env ruby require 'optparse' +require 'thread' require 'ostruct' $stdout.sync = true @@ -65,6 +66,7 @@ unless options.ruby_path end argv = '["' + ARGV * '", "' + '"]' +child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]' debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' options.gems_to_include.each do |gem_path| @@ -78,51 +80,17 @@ require 'ruby-debug-ide/attach/util' require 'ruby-debug-ide/attach/native_debugger' require 'ruby-debug-ide/attach/process_thread' -debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv) -trap('INT') do - unless debugger.exited? - $stderr.puts "backtraces for threads:\n\n" - process_threads = debugger.process_threads - if process_threads - process_threads.each do |thread| - $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" - end - end - debugger.exit - end - exit! -end +child_pids = get_child_pids(options.pid.to_s) +attach_threads = Array.new +attach_threads << attach_and_return_thread(options, options.pid, debugger_loader_path, argv) -debugger.attach_to_process -debugger.set_flags +attach_threads << child_pids.map {|pid| attach_and_return_thread(options, pid, debugger_loader_path, child_argv)} + +attach_threads.each {|thread| thread.join} if options.uid DebugPrinter.print_debug("changing current uid from #{Process.uid} to #{options.uid}") Process::Sys.setuid(options.uid.to_i) end - -if debugger.check_already_under_debug - $stderr.puts "Process #{debugger.pid} is already under debug" - debugger.exit - exit! -end - -should_check_threads_state = true - -while should_check_threads_state - should_check_threads_state = false - debugger.update_threads.each do |thread| - thread.switch - while thread.need_finish_frame - should_check_threads_state = true - thread.finish - end - end -end - -debugger.wait_line_event -debugger.load_debugger -debugger.exit - sleep diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 34d563d..fc03173 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -48,7 +48,7 @@ EOB end opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} - opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} + opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| options.dispatcher_port = dp end @@ -71,6 +71,9 @@ EOB opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do options.attach_mode = true end + opts.on("--ignore-port", "Generate another port") do + options.ignore_port = true + end opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true} opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false} opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do diff --git a/lib/ruby-debug-ide/attach/util.rb b/lib/ruby-debug-ide/attach/util.rb index faa8478..40860d4 100644 --- a/lib/ruby-debug-ide/attach/util.rb +++ b/lib/ruby-debug-ide/attach/util.rb @@ -1,5 +1,76 @@ require 'ruby-debug-ide/attach/lldb' require 'ruby-debug-ide/attach/gdb' +require 'socket' + +def attach_and_return_thread(options, pid, debugger_loader_path, argv) + Thread.new(argv) do |argv| + + debugger = choose_debugger(options.ruby_path, pid, options.gems_to_include, debugger_loader_path, argv) + + trap('INT') do + unless debugger.exited? + $stderr.puts "backtraces for threads:\n\n" + process_threads = debugger.process_threads + if process_threads + process_threads.each do |thread| + $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n" + end + end + debugger.exit + end + exit! + end + + debugger.attach_to_process + debugger.set_flags + + if debugger.check_already_under_debug + $stderr.puts "Process #{debugger.pid} is already under debug" + debugger.exit + exit! + end + + should_check_threads_state = true + + while should_check_threads_state + should_check_threads_state = false + debugger.update_threads.each do |thread| + thread.switch + while thread.need_finish_frame + should_check_threads_state = true + thread.finish + end + end + end + + debugger.wait_line_event + debugger.load_debugger + debugger.exit + end +end + +def get_child_pids(pid) + return [] unless command_exists 'pgrep' + + pids = Array.new + + q = Queue.new + q.push(pid) + + while (!q.empty?) do + pid = q.pop + + pipe = IO.popen("pgrep -P #{pid}") + + pipe.readlines.each do |child| + child_pid = child.strip.to_i + q.push(child_pid) + pids << child_pid + end + end + + pids +end def command_exists(command) checking_command = "checking command #{command} for existence\n" diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index eb96242..fd0d41f 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -19,6 +19,11 @@ def pre_child(options = nil) 'notify_dispatcher' => true ) + if(options.ignore_port) + options.port = find_free_port(options.host) + options.notify_dispatcher = true + end + start_debugger(options) end @@ -39,7 +44,6 @@ def start_debugger(options) Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing Debugger.cli_debug = options.cli_debug - Debugger.prepare_debugger(options) end From 0e58fa4357f1a040d5805e463eca65ad0b0c8862 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Mon, 7 Aug 2017 13:43:21 +0300 Subject: [PATCH 198/302] Optimized unnecessary to_s --- lib/ruby-debug-ide/commands/variables.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/commands/variables.rb b/lib/ruby-debug-ide/commands/variables.rb index ccc5841..33c4f8e 100644 --- a/lib/ruby-debug-ide/commands/variables.rb +++ b/lib/ruby-debug-ide/commands/variables.rb @@ -129,8 +129,7 @@ def execute locals = @state.context.frame_locals(@state.frame_pos) _self = @state.context.frame_self(@state.frame_pos) begin - _self_str = exec_with_allocation_control(_self, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, false) - locals['self'] = _self unless "main" == _self_str + locals['self'] = _self unless TOPLEVEL_BINDING.eval('self') == _self rescue => ex locals['self'] = "" $stderr << "Cannot evaluate self\n#{ex.class.name}: #{ex.message}\n #{ex.backtrace.join("\n ")}" From 2f7b3e0808c415d43888e003b5ec77c5795bdceb Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 7 Aug 2017 14:38:21 +0300 Subject: [PATCH 199/302] bump version --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 560323f..b720ba5 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta5' + IDE_VERSION='0.6.1.beta6' end From 7fda8076920c970f01972d73af223bab2c860347 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Tue, 8 Aug 2017 12:16:49 +0300 Subject: [PATCH 200/302] jruby and error class fix (#116) * jruby and error class fix * Tabs for backtrace output --- lib/ruby-debug-ide/xml_printer.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 5e449d1..aad80f6 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -1,7 +1,9 @@ require 'stringio' require 'cgi' require 'monitor' -require 'objspace' +if (!defined?(JRUBY_VERSION)) + require 'objspace' +end module Debugger @@ -15,7 +17,7 @@ class MemoryLimitError < StandardError attr_reader :message attr_reader :backtrace - def initialize(message, backtrace = '') + def initialize(message, backtrace = []) @message = message @backtrace = backtrace end @@ -25,7 +27,7 @@ class TimeLimitError < StandardError attr_reader :message attr_reader :backtrace - def initialize(message, backtrace = '') + def initialize(message, backtrace = []) @message = message @backtrace = backtrace end @@ -183,7 +185,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o curr_time = Time.now.to_f if ((curr_time - start_time) * 1e3 > time_limit) - curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", "#{caller.map {|l| "\t#{l}"}.join("\n")}") + curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", caller.to_a) inspect_thread.kill end @@ -192,7 +194,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit) - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", "#{caller.map {|l| "\t#{l}"}.join("\n")}") + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", caller.to_a) inspect_thread.kill end end @@ -205,8 +207,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o inspect_thread.kill return result rescue MemoryLimitError, TimeLimitError => e - print_debug(e.message + "\n" + e.backtrace) - + print_debug(e.message + "\n" + e.backtrace.map{|l| "\t#{l}"}.join("\n")) return overflow_message_type.call(e) end @@ -231,7 +232,6 @@ def print_variable(name, value, kind) has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? value_str = exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>" - unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end From b8783c0f71bde9336883212b336a97f96ac12af9 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 8 Aug 2017 12:17:56 +0300 Subject: [PATCH 201/302] bump version --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index b720ba5..43e2521 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta6' + IDE_VERSION='0.6.1.beta7' end From c3890c6932aaa5653c9a52d6605ba75486966e97 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 8 Aug 2017 14:32:17 +0300 Subject: [PATCH 202/302] attach only to ruby child processes --- lib/ruby-debug-ide/attach/util.rb | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/attach/util.rb b/lib/ruby-debug-ide/attach/util.rb index 40860d4..9ab535e 100644 --- a/lib/ruby-debug-ide/attach/util.rb +++ b/lib/ruby-debug-ide/attach/util.rb @@ -1,6 +1,7 @@ require 'ruby-debug-ide/attach/lldb' require 'ruby-debug-ide/attach/gdb' require 'socket' +require 'set' def attach_and_return_thread(options, pid, debugger_loader_path, argv) Thread.new(argv) do |argv| @@ -57,7 +58,7 @@ def get_child_pids(pid) q = Queue.new q.push(pid) - while (!q.empty?) do + until q.empty? do pid = q.pop pipe = IO.popen("pgrep -P #{pid}") @@ -69,7 +70,25 @@ def get_child_pids(pid) end end - pids + filter_ruby_processes(pids) +end + +def filter_ruby_processes(pids) + pipe = IO.popen(%Q(lsof -c ruby | awk '{print $2 ":" $9}' | grep -E 'bin/ruby([[:digit:]]+\.?)*$')) + + ruby_processes = Set.new + + pipe.readlines.each do |process| + pid = process.split(/:/).first + ruby_processes.add(pid.to_i) + end + + ruby_processes_pids, non_ruby_processes_pids = pids.partition {|pid| ruby_processes.include? pid} + + DebugPrinter.print_debug("The following child processes was added to attach: #{ruby_processes_pids.join(', ')}") unless ruby_processes_pids.empty? + DebugPrinter.print_debug("The following child are not ruby processes: #{non_ruby_processes_pids.join(', ')}") unless non_ruby_processes_pids.empty? + + ruby_processes_pids end def command_exists(command) @@ -93,4 +112,4 @@ def choose_debugger(ruby_path, pid, gems_to_include, debugger_loader_path, argv) end debugger -end +end \ No newline at end of file From c8dd9490114d14fee8d8d1d3affac29f0424fc67 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 8 Aug 2017 17:43:36 +0300 Subject: [PATCH 203/302] bump version --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 43e2521..a2776bc 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta7' + IDE_VERSION='0.6.1.beta8' end From 25e81518ebc42f1a97ea058e2ff5defda0c1a320 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Thu, 10 Aug 2017 17:34:29 +0300 Subject: [PATCH 204/302] set evaluation timeout for child processes(https://youtrack.jetbrains.com/issue/RUBY-19948) --- lib/ruby-debug-ide/multiprocess/pre_child.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index fd0d41f..4d8f65d 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -16,7 +16,8 @@ def pre_child(options = nil) 'tracing' => false, 'int_handler' => true, 'cli_debug' => (ENV['DEBUGGER_CLI_DEBUG'] == 'true'), - 'notify_dispatcher' => true + 'notify_dispatcher' => true, + 'evaluation_timeout' => 10 ) if(options.ignore_port) @@ -43,6 +44,7 @@ def start_debugger(options) # set options Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing + Debugger.evaluation_timeout = options.evaluation_timeout Debugger.cli_debug = options.cli_debug Debugger.prepare_debugger(options) end From 802b46aaa94a2aead3ce4b42466959368a02747c Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 8 Aug 2017 19:18:39 +0300 Subject: [PATCH 205/302] dont use exec_with_allocation for old ruby versions --- lib/ruby-debug-ide/xml_printer.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index aad80f6..e4a92db 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -168,6 +168,8 @@ def print_string(string) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) + return value.send exec_method if(RUBY_VERSION < '2.0') + check_memory_limit = true if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) check_memory_limit = false From 6ef0dce3dafa6d40a4a04069b77fa0af2b7cff58 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 21 Aug 2017 10:54:44 +0300 Subject: [PATCH 206/302] tune encoding version check to formally accept 2.0 origin: RUBY-15434 --- lib/ruby-debug-ide/command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 5f099be..dffd1a2 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -118,7 +118,7 @@ def timeout(sec) def debug_eval(str, b = get_binding) begin str = str.to_s - str.force_encoding('UTF-8') if(RUBY_VERSION > '2.0') + str.force_encoding('UTF-8') if(RUBY_VERSION >= '2.0') to_inspect = Command.unescape_incoming(str) max_time = Debugger.evaluation_timeout @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time) From 4e632dafe6a01e9e19c71e179393511777a966f8 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Wed, 9 Aug 2017 02:50:29 +0300 Subject: [PATCH 207/302] fix of throwing exceptions in exec_with_allocation_control --- lib/ruby-debug-ide/xml_printer.rb | 60 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index aad80f6..ea101d0 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -15,20 +15,24 @@ module OverflowMessageType class MemoryLimitError < StandardError attr_reader :message + attr_reader :trace_point attr_reader :backtrace - def initialize(message, backtrace = []) + def initialize(message, trace_point, backtrace = []) @message = message + @trace_point = trace_point @backtrace = backtrace end end class TimeLimitError < StandardError attr_reader :message + attr_reader :trace_point attr_reader :backtrace - def initialize(message, backtrace = []) + def initialize(message, trace_point, backtrace = []) @message = message + @trace_point = trace_point @backtrace = backtrace end end @@ -168,47 +172,45 @@ def print_string(string) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - check_memory_limit = true - if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0) - check_memory_limit = false - end + check_memory_limit = !defined?(JRUBY_VERSION) && ENV['DEBUGGER_MEMORY_LIMIT'].to_i > 0 curr_thread = Thread.current - result = nil - inspect_thread = DebugThread.start { + result = nil + inspect_thread = DebugThread.start do start_alloc_size = ObjectSpace.memsize_of_all if (check_memory_limit) start_time = Time.now.to_f - trace = TracePoint.new(:c_call, :call) do |tp| + trace_point = TracePoint.new(:c_call, :call) do | | + next unless Thread.current == inspect_thread + next unless rand > 0.75 - if (rand > 0.75) - curr_time = Time.now.to_f + curr_time = Time.now.to_f - if ((curr_time - start_time) * 1e3 > time_limit) - curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", caller.to_a) - inspect_thread.kill - end + if (curr_time - start_time) * 1e3 > time_limit + curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", caller.to_a, trace_point) + end - if (check_memory_limit) - curr_alloc_size = ObjectSpace.memsize_of_all - start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) + if check_memory_limit + curr_alloc_size = ObjectSpace.memsize_of_all + start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) - if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit) - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", caller.to_a) - inspect_thread.kill - end + if curr_alloc_size - start_alloc_size > 1e6 * memory_limit + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", caller.to_a, trace_point) end end - end.enable { - result = value.send exec_method - } - } + end + trace_point.enable + result = value.send exec_method + trace_point.disable + end inspect_thread.join - inspect_thread.kill return result rescue MemoryLimitError, TimeLimitError => e - print_debug(e.message + "\n" + e.backtrace.map{|l| "\t#{l}"}.join("\n")) + e.trace_point.disable + print_debug(e.message + "\n" + e.backtrace.map {|l| "\t#{l}"}.join("\n")) return overflow_message_type.call(e) + ensure + inspect_thread.kill if inspect_thread && inspect_thread.alive? end def print_variable(name, value, kind) @@ -512,4 +514,4 @@ def build_value_attr(escaped_value_str) end -end +end \ No newline at end of file From 82ff29e1b5d64d918eaf6637ce1c621a04eb4b39 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 21 Aug 2017 11:22:55 +0300 Subject: [PATCH 208/302] extract common superclass from TL&ML Errors --- lib/ruby-debug-ide/xml_printer.rb | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index ea101d0..4a26e5f 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -13,7 +13,7 @@ module OverflowMessageType SPECIAL_SYMBOL_MESSAGE = lambda {|e| ''} end - class MemoryLimitError < StandardError + class ExecError < StandardError attr_reader :message attr_reader :trace_point attr_reader :backtrace @@ -25,17 +25,9 @@ def initialize(message, trace_point, backtrace = []) end end - class TimeLimitError < StandardError - attr_reader :message - attr_reader :trace_point - attr_reader :backtrace + class MemoryLimitError < ExecError; end - def initialize(message, trace_point, backtrace = []) - @message = message - @trace_point = trace_point - @backtrace = backtrace - end - end + class TimeLimitError < ExecError; end class XmlPrinter # :nodoc: class ExceptionProxy @@ -205,7 +197,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o end inspect_thread.join return result - rescue MemoryLimitError, TimeLimitError => e + rescue ExecError => e e.trace_point.disable print_debug(e.message + "\n" + e.backtrace.map {|l| "\t#{l}"}.join("\n")) return overflow_message_type.call(e) From c9522b45dfe4673cb75b9c174e8f18e5ffb4b8c1 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 21 Aug 2017 11:35:18 +0300 Subject: [PATCH 209/302] remove parentheses --- lib/ruby-debug-ide/xml_printer.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 28e962c..87dcb86 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -164,14 +164,14 @@ def print_string(string) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - return value.send exec_method if(RUBY_VERSION < '2.0') + return value.send exec_method if RUBY_VERSION < '2.0' check_memory_limit = !defined?(JRUBY_VERSION) && ENV['DEBUGGER_MEMORY_LIMIT'].to_i > 0 curr_thread = Thread.current result = nil inspect_thread = DebugThread.start do - start_alloc_size = ObjectSpace.memsize_of_all if (check_memory_limit) + start_alloc_size = ObjectSpace.memsize_of_all if check_memory_limit start_time = Time.now.to_f trace_point = TracePoint.new(:c_call, :call) do | | @@ -186,7 +186,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o if check_memory_limit curr_alloc_size = ObjectSpace.memsize_of_all - start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size) + start_alloc_size = curr_alloc_size if curr_alloc_size < start_alloc_size if curr_alloc_size - start_alloc_size > 1e6 * memory_limit curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", caller.to_a, trace_point) From 4b2c816bf90943ee6708d4709d08b29699147699 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 21 Aug 2017 11:39:59 +0300 Subject: [PATCH 210/302] fix calls after refactoring --- lib/ruby-debug-ide/xml_printer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 87dcb86..ca60f37 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -181,7 +181,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o curr_time = Time.now.to_f if (curr_time - start_time) * 1e3 > time_limit - curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", caller.to_a, trace_point) + curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", trace_point, caller.to_a) end if check_memory_limit @@ -189,7 +189,7 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o start_alloc_size = curr_alloc_size if curr_alloc_size < start_alloc_size if curr_alloc_size - start_alloc_size > 1e6 * memory_limit - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", caller.to_a, trace_point) + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", trace_point, caller.to_a) end end end From df0314976d2ed7d9678d14f453c9cf2cd49124e8 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 25 Aug 2017 01:49:55 +0300 Subject: [PATCH 211/302] jruby exec_with_allocation_control heuristic --- lib/ruby-debug-ide/xml_printer.rb | 47 +++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index ca60f37..539483d 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -25,9 +25,19 @@ def initialize(message, trace_point, backtrace = []) end end - class MemoryLimitError < ExecError; end + class JrubyTimeLimitError < StandardError + attr_reader :message - class TimeLimitError < ExecError; end + def initialize(message) + @message = message + end + end + + class MemoryLimitError < ExecError; + end + + class TimeLimitError < ExecError; + end class XmlPrinter # :nodoc: class ExceptionProxy @@ -163,10 +173,28 @@ def print_string(string) end end + def jruby_timeout(sec) + return yield if sec == nil or sec.zero? + if Thread.respond_to?(:critical) and Thread.critical + raise ThreadError, "timeout within critical session" + end + begin + x = Thread.current + y = DebugThread.start { + sleep sec + x.raise JrubyTimeLimitError.new("Timeout: evaluation took longer than #{sec} seconds.") if x.alive? + } + yield sec + ensure + y.kill if y and y.alive? + end + end + def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) return value.send exec_method if RUBY_VERSION < '2.0' - check_memory_limit = !defined?(JRUBY_VERSION) && ENV['DEBUGGER_MEMORY_LIMIT'].to_i > 0 + return jruby_timeout(time_limit/1e3) {value.send exec_method} if defined?(JRUBY_VERSION) + curr_thread = Thread.current result = nil @@ -184,13 +212,11 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", trace_point, caller.to_a) end - if check_memory_limit - curr_alloc_size = ObjectSpace.memsize_of_all - start_alloc_size = curr_alloc_size if curr_alloc_size < start_alloc_size + curr_alloc_size = ObjectSpace.memsize_of_all + start_alloc_size = curr_alloc_size if curr_alloc_size < start_alloc_size - if curr_alloc_size - start_alloc_size > 1e6 * memory_limit - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", trace_point, caller.to_a) - end + if curr_alloc_size - start_alloc_size > 1e6 * memory_limit + curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", trace_point, caller.to_a) end end trace_point.enable @@ -203,6 +229,9 @@ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, o e.trace_point.disable print_debug(e.message + "\n" + e.backtrace.map {|l| "\t#{l}"}.join("\n")) return overflow_message_type.call(e) + rescue JrubyTimeLimitError => e + print_debug(e.message) + return overflow_message_type.call(e) ensure inspect_thread.kill if inspect_thread && inspect_thread.alive? end From a2ea597a83d24a0ef014c50a9729cc0ee4bca688 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 25 Aug 2017 01:51:34 +0300 Subject: [PATCH 212/302] heuristic also works for old versions --- lib/ruby-debug-ide/xml_printer.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 539483d..db094f0 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -191,9 +191,8 @@ def jruby_timeout(sec) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - return value.send exec_method if RUBY_VERSION < '2.0' - return jruby_timeout(time_limit/1e3) {value.send exec_method} if defined?(JRUBY_VERSION) + return value.send exec_method if RUBY_VERSION < '2.0' curr_thread = Thread.current From 1e9da6d6dbffe7aee2e85ea686b05beadc9ea83e Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 25 Aug 2017 01:56:57 +0300 Subject: [PATCH 213/302] formatting --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index db094f0..6d03618 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -191,7 +191,7 @@ def jruby_timeout(sec) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - return jruby_timeout(time_limit/1e3) {value.send exec_method} if defined?(JRUBY_VERSION) + return jruby_timeout(time_limit / 1e3) {value.send exec_method} if defined?(JRUBY_VERSION) return value.send exec_method if RUBY_VERSION < '2.0' curr_thread = Thread.current From 90bbdb6920bbb2ebb46b707af33a29f770e6aa06 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 31 Aug 2017 19:11:13 +0300 Subject: [PATCH 214/302] new implementation of execution with allocation control --- lib/ruby-debug-ide/xml_printer.rb | 53 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 6d03618..d1b4523 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -15,17 +15,15 @@ module OverflowMessageType class ExecError < StandardError attr_reader :message - attr_reader :trace_point attr_reader :backtrace - def initialize(message, trace_point, backtrace = []) + def initialize(message, backtrace = []) @message = message - @trace_point = trace_point @backtrace = backtrace end end - class JrubyTimeLimitError < StandardError + class SimpleTimeLimitError < StandardError attr_reader :message def initialize(message) @@ -173,7 +171,7 @@ def print_string(string) end end - def jruby_timeout(sec) + def exec_with_timeout(sec) return yield if sec == nil or sec.zero? if Thread.respond_to?(:critical) and Thread.critical raise ThreadError, "timeout within critical session" @@ -182,7 +180,7 @@ def jruby_timeout(sec) x = Thread.current y = DebugThread.start { sleep sec - x.raise JrubyTimeLimitError.new("Timeout: evaluation took longer than #{sec} seconds.") if x.alive? + x.raise SimpleTimeLimitError.new("Timeout: evaluation took longer than #{sec} seconds.") if x.alive? } yield sec ensure @@ -191,48 +189,57 @@ def jruby_timeout(sec) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - return jruby_timeout(time_limit / 1e3) {value.send exec_method} if defined?(JRUBY_VERSION) + return exec_with_timeout(time_limit * 1e-3) {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) return value.send exec_method if RUBY_VERSION < '2.0' curr_thread = Thread.current + control_thread = Debugger.control_thread result = nil + + trace_queue = Queue.new + inspect_thread = DebugThread.start do - start_alloc_size = ObjectSpace.memsize_of_all if check_memory_limit + start_alloc_size = ObjectSpace.memsize_of_all start_time = Time.now.to_f - trace_point = TracePoint.new(:c_call, :call) do | | - next unless Thread.current == inspect_thread - next unless rand > 0.75 - + trace_point = TracePoint.new(:c_call, :call) do |tp| curr_time = Time.now.to_f if (curr_time - start_time) * 1e3 > time_limit - curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", trace_point, caller.to_a) + trace_queue << TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", caller.to_a) + trace_point.disable + inspect_thread.kill end + next unless rand > 0.75 + curr_alloc_size = ObjectSpace.memsize_of_all start_alloc_size = curr_alloc_size if curr_alloc_size < start_alloc_size if curr_alloc_size - start_alloc_size > 1e6 * memory_limit - curr_thread.raise MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", trace_point, caller.to_a) + trace_queue << MemoryLimitError.new("Out of memory: evaluation of #{exec_method} took more than #{memory_limit}mb.", caller.to_a) + trace_point.disable + inspect_thread.kill end end trace_point.enable result = value.send exec_method + trace_queue << result trace_point.disable end - inspect_thread.join - return result - rescue ExecError => e - e.trace_point.disable - print_debug(e.message + "\n" + e.backtrace.map {|l| "\t#{l}"}.join("\n")) - return overflow_message_type.call(e) - rescue JrubyTimeLimitError => e + + while(mes = trace_queue.pop) + if(mes.is_a? TimeLimitError or mes.is_a? MemoryLimitError) + print_debug(mes.message + "\n" + mes.backtrace.map {|l| "\t#{l}"}.join("\n")) + return overflow_message_type.call(mes) + else + return mes + end + end + rescue SimpleTimeLimitError => e print_debug(e.message) return overflow_message_type.call(e) - ensure - inspect_thread.kill if inspect_thread && inspect_thread.alive? end def print_variable(name, value, kind) From 02148f5296b5c30ef0b436358a54217c33e9713c Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 31 Aug 2017 19:17:23 +0300 Subject: [PATCH 215/302] option to disable 'to_s' tracing added --- bin/rdebug-ide | 49 +++++++++++++++++-------------- lib/ruby-debug-ide/xml_printer.rb | 2 +- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index fc03173..f595ebb 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -11,20 +11,20 @@ end $stdout.sync=true options = OpenStruct.new( - 'frame_bind' => false, - 'host' => nil, - 'load_mode' => false, - 'port' => 1234, - 'stop' => false, - 'tracing' => false, - 'int_handler' => true, - 'dispatcher_port' => -1, - 'evaluation_timeout' => 10, - 'rm_protocol_extensions' => false, - 'catchpoint_deleted_event' => false, - 'value_as_nested_element' => false, - 'attach_mode' => false, - 'cli_debug' => false + 'frame_bind' => false, + 'host' => nil, + 'load_mode' => false, + 'port' => 1234, + 'stop' => false, + 'tracing' => false, + 'int_handler' => true, + 'dispatcher_port' => -1, + 'evaluation_timeout' => 10, + 'rm_protocol_extensions' => false, + 'catchpoint_deleted_event' => false, + 'value_as_nested_element' => false, + 'attach_mode' => false, + 'cli_debug' => false ) opts = OptionParser.new do |opts| @@ -36,20 +36,25 @@ Usage: rdebug-ide is supposed to be called from RDT, NetBeans, RubyMine, or EOB opts.separator "" opts.separator "Options:" - + + Debugger.trace_to_s = true + opts.on("--evaluation-control", "trace to_s evaluation") do + Debugger.trace_to_s = true + end + ENV['DEBUGGER_MEMORY_LIMIT'] = '10' - opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit| - ENV['DEBUGGER_MEMORY_LIMIT'] = limit + opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit| + ENV['DEBUGGER_MEMORY_LIMIT'] = limit.to_s end - + ENV['INSPECT_TIME_LIMIT'] = '100' - opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit| - ENV['INSPECT_TIME_LIMIT'] = limit + opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit| + ENV['INSPECT_TIME_LIMIT'] = limit.to_s end opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} - opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| + opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| options.dispatcher_port = dp end opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout| @@ -133,7 +138,7 @@ if options.dispatcher_port != -1 end Debugger::MultiProcess.do_monkey - ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB'] + ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB'] old_opts = ENV['RUBYOPT'] || '' starter = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter" unless old_opts.include? starter diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index d1b4523..11a5531 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -190,7 +190,7 @@ def exec_with_timeout(sec) def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) return exec_with_timeout(time_limit * 1e-3) {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) - return value.send exec_method if RUBY_VERSION < '2.0' + return value.send exec_method if !Debugger.trace_to_s curr_thread = Thread.current control_thread = Debugger.control_thread From a8f6237814b9b6f3f006ee51067b863a37a37e77 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 31 Aug 2017 19:25:26 +0300 Subject: [PATCH 216/302] option to disable 'to_s' tracing added --- lib/ruby-debug-ide.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index d100fe5..0198c09 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -29,22 +29,22 @@ def print_debug(*args) end def cleanup_backtrace(backtrace) - cleared = [] - return cleared unless backtrace - backtrace.each do |line| - if line.index(File.expand_path(File.dirname(__FILE__) + "/..")) == 0 - next - end - if line.index("-e:1") == 0 - break - end - cleared << line - end - cleared + cleared = [] + return cleared unless backtrace + backtrace.each do |line| + if line.index(File.expand_path(File.dirname(__FILE__) + "/..")) == 0 + next + end + if line.index("-e:1") == 0 + break + end + cleared << line + end + cleared end attr_accessor :attached - attr_accessor :cli_debug, :xml_debug, :evaluation_timeout + attr_accessor :cli_debug, :xml_debug, :evaluation_timeout, :trace_to_s attr_accessor :control_thread attr_reader :interface # protocol extensions From 7a6edb39e039c604afb43d742b121d0c2b143cd0 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 31 Aug 2017 19:31:23 +0300 Subject: [PATCH 217/302] cleanup --- bin/rdebug-ide | 2 +- lib/ruby-debug-ide/xml_printer.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index f595ebb..63a10fd 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -37,7 +37,7 @@ EOB opts.separator "" opts.separator "Options:" - Debugger.trace_to_s = true + Debugger.trace_to_s = false opts.on("--evaluation-control", "trace to_s evaluation") do Debugger.trace_to_s = true end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 11a5531..d453e9a 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -189,8 +189,9 @@ def exec_with_timeout(sec) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - return exec_with_timeout(time_limit * 1e-3) {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) return value.send exec_method if !Debugger.trace_to_s + return exec_with_timeout(time_limit * 1e-3) {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) + curr_thread = Thread.current control_thread = Debugger.control_thread From 80b1e8b7f31b706ed4a81fc6bded9c311b037eb0 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 31 Aug 2017 19:54:35 +0300 Subject: [PATCH 218/302] useless inheritance deleted --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index d453e9a..3af4baa 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -13,7 +13,7 @@ module OverflowMessageType SPECIAL_SYMBOL_MESSAGE = lambda {|e| ''} end - class ExecError < StandardError + class ExecError attr_reader :message attr_reader :backtrace From c9361b192db54839caa4f95068a76970013178de Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 31 Aug 2017 20:55:52 +0300 Subject: [PATCH 219/302] error message for exec_with_timeout changed --- lib/ruby-debug-ide/xml_printer.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 3af4baa..30801d1 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -171,7 +171,7 @@ def print_string(string) end end - def exec_with_timeout(sec) + def exec_with_timeout(sec, error_message) return yield if sec == nil or sec.zero? if Thread.respond_to?(:critical) and Thread.critical raise ThreadError, "timeout within critical session" @@ -180,7 +180,7 @@ def exec_with_timeout(sec) x = Thread.current y = DebugThread.start { sleep sec - x.raise SimpleTimeLimitError.new("Timeout: evaluation took longer than #{sec} seconds.") if x.alive? + x.raise SimpleTimeLimitError.new(error_message) if x.alive? } yield sec ensure @@ -190,7 +190,7 @@ def exec_with_timeout(sec) def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) return value.send exec_method if !Debugger.trace_to_s - return exec_with_timeout(time_limit * 1e-3) {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) + return exec_with_timeout(time_limit * 1e-3, "Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.") {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) curr_thread = Thread.current From 17a5371902a6cfe5e0ff31f2bfa61b13b27a13e6 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 1 Sep 2017 14:45:30 +0300 Subject: [PATCH 220/302] bump --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index a2776bc..deb8ad5 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta8' + IDE_VERSION='0.6.1.beta9' end From efef1e502376b74b2789d5185a1987265bcf1627 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 13 Sep 2017 04:17:50 +0300 Subject: [PATCH 221/302] Add official JB badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9e4024d..90df01e 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,5 @@ # ruby-debug-ide An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine. +[![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![Gem Version](https://badge.fury.io/rb/ruby-debug-ide.svg)][gem] From f67c733db1e649f0f54b24acdebd6ec03f5554f5 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 7 Nov 2017 14:10:34 +0300 Subject: [PATCH 222/302] changed require 'objectspace' to include ObjectSpace --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 30801d1..1f9f234 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -2,7 +2,7 @@ require 'cgi' require 'monitor' if (!defined?(JRUBY_VERSION)) - require 'objspace' + include ObjectSpace end module Debugger From fe9ed572f051208ab2a3b4c1ef8c81bf13f9f6d4 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Tue, 14 Nov 2017 15:27:16 +0300 Subject: [PATCH 223/302] 2.5.0 does not produce an empty statement (#127) Now new line token is a condition for continued command, so the whitespace was added to the end of the command https://github.com/ruby/ruby/commit/f14f0d34641ece73d77781856eed70de760f9d9f --- lib/ruby-debug-ide/commands/expression_info.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index 795ca2d..a03bc83 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -9,7 +9,7 @@ def regexp end def execute - string_to_parse = Command.unescape_incoming(@match.post_match) + "\n\n\n" + string_to_parse = Command.unescape_incoming(@match.post_match) + " \n\n\n" total_lines = string_to_parse.count("\n") + 1 lexer = RubyLex.new From 92ffd69e3cb8f473dc2accc32fd35cb20e4d6b56 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 14 Nov 2017 18:48:27 +0300 Subject: [PATCH 224/302] bump version --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index deb8ad5..6aca7c7 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta9' + IDE_VERSION='0.6.1.beta10' end From 1faaa9877b4bd9c0b8d7602b7602c5c273f49ccf Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 16 Nov 2017 15:08:04 +0300 Subject: [PATCH 225/302] move evaluation control opts near eval timeout --- bin/rdebug-ide | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 63a10fd..1843b35 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -37,6 +37,14 @@ EOB opts.separator "" opts.separator "Options:" + opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} + opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} + opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| + options.dispatcher_port = dp + end + opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout| + options.evaluation_timeout = timeout + end Debugger.trace_to_s = false opts.on("--evaluation-control", "trace to_s evaluation") do Debugger.trace_to_s = true @@ -52,14 +60,6 @@ EOB ENV['INSPECT_TIME_LIMIT'] = limit.to_s end - opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} - opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} - opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| - options.dispatcher_port = dp - end - opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout| - options.evaluation_timeout = timeout - end opts.on('--stop', 'stop when the script is loaded') {options.stop = true} opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true} opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true} From cfb1f0616898d99aeef820a3b545d84a2f0bd1c5 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 16 Nov 2017 16:56:24 +0300 Subject: [PATCH 226/302] unify time/memlimit opts with other ones; fix objspace req --- bin/rdebug-ide | 23 +++++++++++------ lib/ruby-debug-ide.rb | 3 ++- lib/ruby-debug-ide/multiprocess/pre_child.rb | 8 +++++- lib/ruby-debug-ide/xml_printer.rb | 27 ++++++++------------ 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 1843b35..a72dfd1 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -20,6 +20,9 @@ options = OpenStruct.new( 'int_handler' => true, 'dispatcher_port' => -1, 'evaluation_timeout' => 10, + 'trace_to_s' => false, + 'debugger_memory_limit' => 10, + 'inspect_time_limit' => 100, 'rm_protocol_extensions' => false, 'catchpoint_deleted_event' => false, 'value_as_nested_element' => false, @@ -45,19 +48,20 @@ EOB opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout| options.evaluation_timeout = timeout end - Debugger.trace_to_s = false - opts.on("--evaluation-control", "trace to_s evaluation") do - Debugger.trace_to_s = true - end + opts.on("--evaluation-control", "trace to_s evaluation") {options.trace_to_s = true} - ENV['DEBUGGER_MEMORY_LIMIT'] = '10' opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit| - ENV['DEBUGGER_MEMORY_LIMIT'] = limit.to_s + if defined?(JRUBY_VERSION) || RUBY_VERSION < '2.0' + $stderr.puts "Evaluation memory limit is ineffective in JRuby and MRI < 2.0" + limit = 0 + end + options.debugger_memory_limit = limit + options.trace_to_s ||= limit > 0 end - ENV['INSPECT_TIME_LIMIT'] = '100' opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit| - ENV['INSPECT_TIME_LIMIT'] = limit.to_s + options.inspect_time_limit = limit + options.trace_to_s ||= limit > 0 end opts.on('--stop', 'stop when the script is loaded') {options.stop = true} @@ -157,6 +161,9 @@ end Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing Debugger.evaluation_timeout = options.evaluation_timeout +Debugger.trace_to_s = options.trace_to_s && (options.debugger_memory_limit > 0 || options.inspect_time_limit > 0) +Debugger.debugger_memory_limit = options.debugger_memory_limit +Debugger.inspect_time_limit = options.inspect_time_limit Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 0198c09..7482da3 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -44,7 +44,8 @@ def cleanup_backtrace(backtrace) end attr_accessor :attached - attr_accessor :cli_debug, :xml_debug, :evaluation_timeout, :trace_to_s + attr_accessor :cli_debug, :xml_debug, :evaluation_timeout + attr_accessor :trace_to_s, :debugger_memory_limit, :inspect_time_limit attr_accessor :control_thread attr_reader :interface # protocol extensions diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 4d8f65d..4a349fd 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -17,7 +17,10 @@ def pre_child(options = nil) 'int_handler' => true, 'cli_debug' => (ENV['DEBUGGER_CLI_DEBUG'] == 'true'), 'notify_dispatcher' => true, - 'evaluation_timeout' => 10 + 'evaluation_timeout' => 10, + 'trace_to_s' => false, + 'debugger_memory_limit' => 10, + 'inspect_time_limit' => 100 ) if(options.ignore_port) @@ -45,6 +48,9 @@ def start_debugger(options) Debugger.keep_frame_binding = options.frame_bind Debugger.tracing = options.tracing Debugger.evaluation_timeout = options.evaluation_timeout + Debugger.trace_to_s = options.trace_to_s + Debugger.debugger_memory_limit = options.debugger_memory_limit + Debugger.inspect_time_limit = options.inspect_time_limit Debugger.cli_debug = options.cli_debug Debugger.prepare_debugger(options) end diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 1f9f234..8014715 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -1,9 +1,6 @@ require 'stringio' require 'cgi' require 'monitor' -if (!defined?(JRUBY_VERSION)) - include ObjectSpace -end module Debugger @@ -153,7 +150,7 @@ def print_hash(hash) if k.class.name == "String" name = '\'' + k + '\'' else - name = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) + name = exec_with_allocation_control(k, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) end print_variable(name, hash[k], 'instance') } @@ -189,18 +186,16 @@ def exec_with_timeout(sec, error_message) end def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) - return value.send exec_method if !Debugger.trace_to_s - return exec_with_timeout(time_limit * 1e-3, "Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.") {value.send exec_method} if defined?(JRUBY_VERSION) || memory_limit <= 0 || (RUBY_VERSION < '2.0' && time_limit > 0) + return value.send exec_method unless Debugger.trace_to_s + if defined?(JRUBY_VERSION) || RUBY_VERSION < '2.0' || memory_limit <= 0 + return exec_with_timeout(time_limit * 1e-3, "Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.") { value.send exec_method } + end - curr_thread = Thread.current - control_thread = Debugger.control_thread - - result = nil - + require 'objspace' trace_queue = Queue.new - inspect_thread = DebugThread.start do + DebugThread.start do start_alloc_size = ObjectSpace.memsize_of_all start_time = Time.now.to_f @@ -263,7 +258,7 @@ def print_variable(name, value, kind) else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - value_str = exec_with_allocation_control(value, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>" + value_str = exec_with_allocation_control(value, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end @@ -489,7 +484,7 @@ def max_compact_name_size def compact_array_str(value) slice = value[0..10] - compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, OverflowMessageType::NIL_MESSAGE) + compact = exec_with_allocation_control(slice, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :inspect, OverflowMessageType::NIL_MESSAGE) if compact && value.size != slice.size compact[0..compact.size - 2] + ", ...]" @@ -501,14 +496,14 @@ def compact_hash_str(value) keys_strings = Hash.new slice = value.sort_by do |k, _| - keys_string = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) + keys_string = exec_with_allocation_control(k, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) keys_strings[k] = keys_string keys_string end[0..5] compact = slice.map do |kv| key_string = keys_strings[kv[0]] - value_string = exec_with_allocation_control(kv[1], ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) + value_string = exec_with_allocation_control(kv[1], Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) "#{key_string}: #{handle_binary_data(value_string)}" end.join(", ") "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" From 845abb10fe07bb867cf20acac1ca81c584382ee8 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 16 Nov 2017 16:58:54 +0300 Subject: [PATCH 227/302] remove constant parameters --- lib/ruby-debug-ide/xml_printer.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 8014715..0ad7d00 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -150,7 +150,7 @@ def print_hash(hash) if k.class.name == "String" name = '\'' + k + '\'' else - name = exec_with_allocation_control(k, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) + name = exec_with_allocation_control(k, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) end print_variable(name, hash[k], 'instance') } @@ -185,9 +185,12 @@ def exec_with_timeout(sec, error_message) end end - def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type) + def exec_with_allocation_control(value, exec_method, overflow_message_type) return value.send exec_method unless Debugger.trace_to_s + memory_limit = Debugger.debugger_memory_limit + time_limit = Debugger.inspect_time_limit + if defined?(JRUBY_VERSION) || RUBY_VERSION < '2.0' || memory_limit <= 0 return exec_with_timeout(time_limit * 1e-3, "Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.") { value.send exec_method } end @@ -258,7 +261,7 @@ def print_variable(name, value, kind) else has_children = !value.instance_variables.empty? || !value.class.class_variables.empty? - value_str = exec_with_allocation_control(value, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>" + value_str = exec_with_allocation_control(value, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) || 'nil' rescue "<#to_s method raised exception: #{$!}>" unless value_str.is_a?(String) value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String." end @@ -484,7 +487,7 @@ def max_compact_name_size def compact_array_str(value) slice = value[0..10] - compact = exec_with_allocation_control(slice, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :inspect, OverflowMessageType::NIL_MESSAGE) + compact = exec_with_allocation_control(slice, :inspect, OverflowMessageType::NIL_MESSAGE) if compact && value.size != slice.size compact[0..compact.size - 2] + ", ...]" @@ -496,14 +499,14 @@ def compact_hash_str(value) keys_strings = Hash.new slice = value.sort_by do |k, _| - keys_string = exec_with_allocation_control(k, Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) + keys_string = exec_with_allocation_control(k, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) keys_strings[k] = keys_string keys_string end[0..5] compact = slice.map do |kv| key_string = keys_strings[kv[0]] - value_string = exec_with_allocation_control(kv[1], Debugger.debugger_memory_limit, Debugger.inspect_time_limit, :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) + value_string = exec_with_allocation_control(kv[1], :to_s, OverflowMessageType::SPECIAL_SYMBOL_MESSAGE) "#{key_string}: #{handle_binary_data(value_string)}" end.join(", ") "{" + compact + (slice.size != value.size ? ", ..." : "") + "}" From c24646fc158de2d770263a056f18484d0d7b6bee Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 16 Nov 2017 17:23:27 +0300 Subject: [PATCH 228/302] add dependency on debase/ruby-debug-base --- ruby-debug-ide.gemspec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruby-debug-ide.gemspec b/ruby-debug-ide.gemspec index 7cd29ef..4c974f3 100644 --- a/ruby-debug-ide.gemspec +++ b/ruby-debug-ide.gemspec @@ -42,6 +42,12 @@ EOF spec.extensions << "ext/mkrf_conf.rb" unless ENV['NO_EXT'] spec.add_dependency("rake", ">= 0.8.1") + if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION) + spec.add_dependency 'ruby-debug-base' + else + spec.add_dependency 'debase', '~> 0.2.2.beta11' + end + spec.required_ruby_version = '>= 1.8.2' spec.date = DateTime.now spec.rubyforge_project = 'debug-commons' From fca6ea4f96157a9176ade92e1ad7af5c21c8cbaf Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 16 Nov 2017 18:03:31 +0300 Subject: [PATCH 229/302] Revert "add dependency on debase/ruby-debug-base" This reverts commit c24646f --- ruby-debug-ide.gemspec | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ruby-debug-ide.gemspec b/ruby-debug-ide.gemspec index 4c974f3..7cd29ef 100644 --- a/ruby-debug-ide.gemspec +++ b/ruby-debug-ide.gemspec @@ -42,12 +42,6 @@ EOF spec.extensions << "ext/mkrf_conf.rb" unless ENV['NO_EXT'] spec.add_dependency("rake", ">= 0.8.1") - if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION) - spec.add_dependency 'ruby-debug-base' - else - spec.add_dependency 'debase', '~> 0.2.2.beta11' - end - spec.required_ruby_version = '>= 1.8.2' spec.date = DateTime.now spec.rubyforge_project = 'debug-commons' From 58985e579341ec30775e4f39ac0af30fa7818564 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 4 Dec 2017 19:14:04 +0300 Subject: [PATCH 230/302] revert unlucky variable removal --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 0ad7d00..de425f5 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -198,7 +198,7 @@ def exec_with_allocation_control(value, exec_method, overflow_message_type) require 'objspace' trace_queue = Queue.new - DebugThread.start do + inspect_thread = DebugThread.start do start_alloc_size = ObjectSpace.memsize_of_all start_time = Time.now.to_f From bf7f78e38af8466572e5a314585e98ff13dad7ae Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 5 Dec 2017 19:32:38 +0300 Subject: [PATCH 231/302] bump version to beta11 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 6aca7c7..3287e97 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta10' + IDE_VERSION='0.6.1.beta11' end From f6ece22511b30b98523332ab151a26873fc1e423 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 21 Nov 2017 22:23:32 +0300 Subject: [PATCH 232/302] tests fixes (cherry picked from commit ac9e8b1) (cherry picked from commit a492b11) --- Gemfile | 1 + lib/ruby-debug-ide.rb | 2 +- test-base/test_base.rb | 5 ++++- test-base/threads_and_frames_test.rb | 18 +++++++++++++++--- test-base/variables_test.rb | 11 +++++++---- test/ruby-debug/xml_printer_test.rb | 9 ++++++--- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Gemfile b/Gemfile index 2ee4fb3..78ab332 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,7 @@ source "http://rubygems.org/" gem "ruby-debug-base", :platforms => [:jruby, :ruby_18, :mingw_18] gem "ruby-debug-base19x", ">= 0.11.30.pre4", :platforms => [:ruby_19, :mingw_19] +gem "debase", ">= 0.2.2.beta11", :platforms => [:ruby_20, :mingw_20, :ruby_21, :mingw_21, :ruby_22, :mingw_22, :ruby_23, :mingw_23, :ruby_24, :mingw_24] gemspec diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 7482da3..62c0671 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -112,7 +112,7 @@ def start_control(host, port, notify_dispatcher) # "localhost" and nil have problems on some systems. host ||= '127.0.0.1' server = TCPServer.new(host, port) - print_greeting_msg($stderr, host, port) + print_greeting_msg($stderr, host, port) if defined? IDE_VERSION notify_dispatcher(port) if notify_dispatcher while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug diff --git a/test-base/test_base.rb b/test-base/test_base.rb index 3399c8b..afc3ab3 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -86,7 +86,7 @@ def start_ruby_process(script) @port = TestBase.find_free_port cmd = debug_command(script, @port) debug "Starting: #{cmd}\n" - + Thread.new do if RUBY_VERSION < '1.9' (_, p_out, p_err) = Open3.popen3(cmd) @@ -222,7 +222,9 @@ def assert_suspension(exp_file, exp_line, exp_frames, exp_thread_id=1) suspension = read_suspension assert_equal(exp_file, suspension.file) assert_equal(exp_line, suspension.line) + exp_frames += 2 if Debugger::FRONT_END == "debase" assert_equal(exp_frames, suspension.frames) + exp_thread_id += 1 if Debugger::FRONT_END == "debase" assert_equal(exp_thread_id, suspension.threadId) end @@ -271,6 +273,7 @@ def assert_exception(exp_file, exp_line, exp_type, exp_thread_id=1) assert_equal(exp_file, exception.file) assert_equal(exp_line, exception.line) assert_equal(exp_type, exception.type) + exp_thread_id += 1 if Debugger::FRONT_END == "debase" assert_equal(exp_thread_id, exception.threadId) assert_not_nil(exception.message) end diff --git a/test-base/threads_and_frames_test.rb b/test-base/threads_and_frames_test.rb index c96b19a..e04cc8f 100644 --- a/test-base/threads_and_frames_test.rb +++ b/test-base/threads_and_frames_test.rb @@ -14,7 +14,11 @@ def test_frames assert_breakpoint_added_no(2) send_ruby("w") frames = read_frames - assert_equal(2, frames.length) + + needed_frame_length = 2 + needed_frame_length += 2 if Debugger::FRONT_END == "debase" + assert_equal(needed_frame_length, frames.length) + frame1 = frames[0] assert_equal(@test2_path, frame1.file) assert_equal(1, frame1.no) @@ -27,7 +31,11 @@ def test_frames assert_test_breakpoint(4) send_ruby("w") frames = read_frames - assert_equal(1, frames.length) + + needed_frame_length = 1 + needed_frame_length += 2 if Debugger::FRONT_END == "debase" + + assert_equal(needed_frame_length, frames.length) send_cont # test:4 -> test2:3 assert_breakpoint("test2.rb", 3) send_cont # test2:3 -> finish @@ -42,7 +50,11 @@ def test_frames_when_thread_spawned "def calc", "5 + 5", "end", "start_thread()", "calc()"] run_to_line(5) send_ruby("w") - assert_equal(2, read_frames.length) + + needed_length = 2 + needed_length += 2 if Debugger::FRONT_END == "debase" + + assert_equal(needed_length, read_frames.length) send_cont end diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index e0d3140..7586050 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# encoding: utf-8 $:.unshift File.join(File.dirname(__FILE__), "..", "lib") @@ -25,7 +26,7 @@ def test_variable_with_xml_content {:name => "stringA"}, {:name => "testHashValue"}) # will receive '' - assert_equal("", variables[0].value) + assert_equal(CGI.escapeHTML(""), variables[0].value) assert_local(variables[0]) # the testHashValue contains an example, where the name consists of special # characters @@ -99,10 +100,12 @@ def test_variable_local end def test_variable_instance - create_socket ["require 'test2.rb'", "custom_object=Test2.new", "puts custom_object"] + create_socket ["require_relative 'test2.rb'", "custom_object=Test2.new", "puts custom_object"] create_test2 ["class Test2", "def initialize", "@y=5", "end", "def to_s", "'test'", "end", "end"] run_to("test2.rb", 6) - send_ruby("frame 3; v i custom_object") + frame_number = 3 + frame_number -= 1 if Debugger::FRONT_END == "debase" + send_ruby("frame #{frame_number}; v i custom_object") assert_variables(read_variables, 1, {:name => "@y", :value => "5", :type => "Fixnum", :hasChildren => false}) send_cont @@ -128,7 +131,7 @@ def test_variable_hash_with_string_keys {:name => "hash", :hasChildren => true}) send_ruby("v i hash") assert_variables(read_variables, 2, - {:name => "'a'", :value => "z", :type => "String"}) + {:name => CGI.escape_html("'a'"), :value => "z", :type => "String"}) send_cont end diff --git a/test/ruby-debug/xml_printer_test.rb b/test/ruby-debug/xml_printer_test.rb index 08eb537..ab58014 100644 --- a/test/ruby-debug/xml_printer_test.rb +++ b/test/ruby-debug/xml_printer_test.rb @@ -48,8 +48,8 @@ def test_print_frames test_path = File.join(Dir.pwd, 'test.rb') expected = [ "", - "", - "", + "", + "", ""] assert_equal(expected, interface.data) end @@ -64,7 +64,10 @@ def test_print_at_line Debugger.stop end test_path = File.join(Dir.pwd, 'test.rb') - expected = [""] + + #TODO investigate + expected = [""] + assert_equal(expected, interface.data) end From 2c5096cab3cbb364d73a5602e9621a5c1c4f1a1e Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 23 Nov 2017 23:48:39 +0300 Subject: [PATCH 233/302] additional require debase from command.rb Sometimes it is evaluating before the ruby-debug-ide.rb, from where it normally requires --- lib/ruby-debug-ide/command.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index dffd1a2..e6ee3e1 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -1,3 +1,9 @@ +if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION) + require 'ruby-debug-base' +else + require 'debase' +end + require 'ruby-debug-ide/helper' require 'delegate' From 9c32ff423f2add09b63355cc2a3f975c6a232376 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 7 Dec 2017 18:19:27 +0300 Subject: [PATCH 234/302] added `test_to_s_timelimit` test --- test-base/variables_test.rb | 28 ++++++++++++++++++++++++++++ test/rd_test_base.rb | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 7586050..7ab798b 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -199,6 +199,34 @@ def test_to_s_raises_exception send_cont end + def test_to_s_timelimit + create_socket ['class A', + 'def to_s', + 'a = 1', + 'loop do', + 'a = a + 1', + 'sleep 1', + 'break if (a > 2)', + 'end', + 'a.to_s', + 'end', + 'end', + 'b = Hash.new', + 'b[A.new] = A.new', + 'b[1] = A.new', + 'puts b #bp here'] + run_to_line(15) + send_ruby('v l') + assert_variables(read_variables, 1, + {:name => "b", :value => "Hash (2 elements)", :type => "Hash"}) + + send_ruby("v i b") + assert_variables(read_variables, 2, + {:name => "Timeout: evaluation of to_s took longer than 100ms.", :value => "Timeout: evaluation of to_s took longer than 100ms.", :type => "A"}, + {:name => "1", :value => "Timeout: evaluation of to_s took longer than 100ms.", :type => "A"}) + send_cont + end + def assert_xml(expected_xml, actual_xml) # XXX is there a better way then html_escape in standard libs? assert_equal(ERB::Util.html_escape(expected_xml), actual_xml) diff --git a/test/rd_test_base.rb b/test/rd_test_base.rb index d872f4e..7d29edc 100644 --- a/test/rd_test_base.rb +++ b/test/rd_test_base.rb @@ -24,7 +24,7 @@ def debug_command(script, port) cmd << " -J-Xdebug -J-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y" if jruby? and debug_jruby? cmd << " -I 'lib:#{File.dirname(script)}' #{@rdebug_ide}" + (@verbose_server ? " -d" : "") + - " -p #{port} -- '#{script}'" + " -p #{port} --evaluation-control --time-limit 100 --memory-limit 0 -- '#{script}'" end def start_debugger From 9b2a4de5b4b33cf1be9af00e1e49dc685f3da4df Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 11 Dec 2017 23:48:20 +0300 Subject: [PATCH 235/302] update debase dependency to use opened attributes for tests --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 78ab332..c2689bf 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source "http://rubygems.org/" gem "ruby-debug-base", :platforms => [:jruby, :ruby_18, :mingw_18] gem "ruby-debug-base19x", ">= 0.11.30.pre4", :platforms => [:ruby_19, :mingw_19] -gem "debase", ">= 0.2.2.beta11", :platforms => [:ruby_20, :mingw_20, :ruby_21, :mingw_21, :ruby_22, :mingw_22, :ruby_23, :mingw_23, :ruby_24, :mingw_24] +gem "debase", ">= 0.2.2.beta12", :platforms => [:ruby_20, :mingw_20, :ruby_21, :mingw_21, :ruby_22, :mingw_22, :ruby_23, :mingw_23, :ruby_24, :mingw_24] gemspec From dd819a0b2de93486cfe8811bf86cd7cb54ca4080 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 00:00:49 +0300 Subject: [PATCH 236/302] expect actual Fixnum/Integer class name as answer --- test-base/variables_test.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 7ab798b..67f9b48 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -47,7 +47,7 @@ def test_variable_in_object {:name => "self", :value => "test", :type => "Test", :hasChildren => true}) send_ruby("v i self") assert_variables(read_variables, 1, - {:name => "@y", :value => "5", :type => "Fixnum", :hasChildren => false, :kind => "instance"}) + {:name => "@y", :value => "5", :type => int_type_name, :hasChildren => false, :kind => "instance"}) send_cont end @@ -60,7 +60,7 @@ def test_class_variables {:name => "self", :hasChildren => true}) send_ruby("v i self") assert_variables(read_variables, 1, - {:name => "@@class_var", :value => "55", :type => "Fixnum", :kind => "class"}) + {:name => "@@class_var", :value => "55", :type => int_type_name, :kind => "class"}) send_cont end @@ -70,7 +70,7 @@ def test_singleton_class_variables run_to_line(3) send_ruby("v i self") assert_variables(read_variables, 1, - {:name => "@@class_var", :value => "55", :type => "Fixnum", :hasChildren => false, :kind => "class"}) + {:name => "@@class_var", :value => "55", :type => int_type_name, :hasChildren => false, :kind => "class"}) send_cont end @@ -95,7 +95,7 @@ def test_variable_local assert_not_nil variables[1].objectId send_ruby("v i " + variables[1].objectId) # 'user' variable assert_variables(read_variables, 1, - {:name => "@id", :value => "22", :type => "Fixnum", :hasChildren => false}) + {:name => "@id", :value => "22", :type => int_type_name, :hasChildren => false}) send_cont end @@ -107,7 +107,7 @@ def test_variable_instance frame_number -= 1 if Debugger::FRONT_END == "debase" send_ruby("frame #{frame_number}; v i custom_object") assert_variables(read_variables, 1, - {:name => "@y", :value => "5", :type => "Fixnum", :hasChildren => false}) + {:name => "@y", :value => "5", :type => int_type_name, :hasChildren => false}) send_cont end @@ -119,7 +119,7 @@ def test_variable_array {:name => "array", :type => "Array", :hasChildren => true}) send_ruby("v i array") assert_variables(read_variables, 2, - {:name => "[0]", :value => "1", :type => "Fixnum"}) + {:name => "[0]", :value => "1", :type => int_type_name}) send_cont end @@ -152,7 +152,7 @@ def test_variable_hash_with_object_keys # get the value send_ruby("frame 1 ; v i " + elements[0].objectId) assert_variables(read_variables, 1, - {:name => "@a", :value => "66", :type => "Fixnum"}) + {:name => "@a", :value => "66", :type => int_type_name}) send_cont end @@ -179,7 +179,7 @@ def test_non_string_from_to_s create_socket ["class BugExample; def to_s; 1; end; end", "b = BugExample.new", "sleep 0.01"] run_to_line(3) send_ruby("v local") - assert_variables(read_variables, 1, {:value => "ERROR: BugExample.to_s method returns Fixnum. Should return String."}) + assert_variables(read_variables, 1, {:value => "ERROR: BugExample.to_s method returns #{int_type_name}. Should return String."}) send_cont end @@ -261,5 +261,11 @@ def assert_variables(vars, count, *expected) end end + private + + def int_type_name + (Fixnum || Integer).name + end + end From 4c8ec4a0a4469fdb900469b2e9f57a2ed0034d0d Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 00:07:08 +0300 Subject: [PATCH 237/302] add travis configuration --- .travis.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d16b673 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: ruby +dist: trusty +os: + - linux + - osx + +rvm: + - 1.9.3 + - 2.0.0 + - 2.1.10 + - 2.2.8 + - 2.3.5 + - 2.4.2 + - 2.5.0-preview1 + - ruby-head + +matrix: + fast_finish: true + allow_failures: + - rvm: ruby-head From 44e88a2d366608c6271d541d087cc9f3b8a6fd86 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 00:27:46 +0300 Subject: [PATCH 238/302] add travis build badge to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 90df01e..d0522d6 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,4 @@ An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and Rub [![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![Gem Version](https://badge.fury.io/rb/ruby-debug-ide.svg)][gem] +[![Build Status](https://travis-ci.org/ruby-debug/ruby-debug-ide.svg?branch=master)](https://travis-ci.org/ruby-debug/ruby-debug-ide) From 771cd3cabbce8b28e0090ebde2486ec8eb8690db Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 10:37:55 +0300 Subject: [PATCH 239/302] do not even try to include debase if ruby < 2.0 --- Gemfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index c2689bf..c324150 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,9 @@ source "http://rubygems.org/" gem "ruby-debug-base", :platforms => [:jruby, :ruby_18, :mingw_18] gem "ruby-debug-base19x", ">= 0.11.30.pre4", :platforms => [:ruby_19, :mingw_19] -gem "debase", ">= 0.2.2.beta12", :platforms => [:ruby_20, :mingw_20, :ruby_21, :mingw_21, :ruby_22, :mingw_22, :ruby_23, :mingw_23, :ruby_24, :mingw_24] +if RUBY_VERSION && RUBY_VERSION >= "2.0" + gem "debase", ">= 0.2.2.beta12", :platforms => [:ruby_20, :mingw_20, :ruby_21, :mingw_21, :ruby_22, :mingw_22, :ruby_23, :mingw_23, :ruby_24, :mingw_24] +end gemspec From 541dd3be03f1a32ee5ef35e6b4e30379475a51ae Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 10:58:48 +0300 Subject: [PATCH 240/302] refactor platforms specification and add mri_25 for debase --- Gemfile | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index c324150..1ec84a9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,19 @@ source "http://rubygems.org/" -gem "ruby-debug-base", :platforms => [:jruby, :ruby_18, :mingw_18] -gem "ruby-debug-base19x", ">= 0.11.30.pre4", :platforms => [:ruby_19, :mingw_19] +# @param [Array] versions compatible ruby versions +# @return [Array] an array with mri platforms of given versions +def mries(*versions) + versions.flat_map do |v| + %w(ruby mingw x64_mingw) + .map { |platform| "#{platform}_#{v}".to_sym unless platform == "x64_mingw" && v < "2.0" } + .delete_if &:nil? + end +end + +gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] +gem "ruby-debug-base19x", ">= 0.11.30.pre4", :platforms => mries('19') if RUBY_VERSION && RUBY_VERSION >= "2.0" - gem "debase", ">= 0.2.2.beta12", :platforms => [:ruby_20, :mingw_20, :ruby_21, :mingw_21, :ruby_22, :mingw_22, :ruby_23, :mingw_23, :ruby_24, :mingw_24] + gem "debase", ">= 0.2.2.beta12", :platforms => mries('20', '21', '22', '23', '24', '25') end gemspec From 179ff307755f358b8f0bc256148c3fa8faa87d67 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 11:09:29 +0300 Subject: [PATCH 241/302] try to install 1.9.3 and 2.0.0 from sources on agents --- .travis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.travis.yml b/.travis.yml index d16b673..3bb50dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,3 +18,17 @@ matrix: fast_finish: true allow_failures: - rvm: ruby-head + + exclude: + - os: osx + rvm: 1.9.3 + - os: osx + rvm: 2.0.0 + + include: + - os: osx + rvm: 1.9.3 + before_script: rvm install ruby-1.9.3 # not binary + - os: osx + rvm: 2.0.0 + before_script: rvm install ruby-2.0.0 # not binary \ No newline at end of file From 35695e006c7f0a52a8738e97f6d49ff8f8e473dc Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 19:04:09 +0300 Subject: [PATCH 242/302] bump ruby-debug-base19 dep version to 0.11.32 This fixes skipped stepping on oneliner blocks --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 1ec84a9..eff0f6c 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ def mries(*versions) end gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] -gem "ruby-debug-base19x", ">= 0.11.30.pre4", :platforms => mries('19') +gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') if RUBY_VERSION && RUBY_VERSION >= "2.0" gem "debase", ">= 0.2.2.beta12", :platforms => mries('20', '21', '22', '23', '24', '25') end From d40d44679e917145660a19f65635b09f5257079f Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 12 Dec 2017 19:06:03 +0300 Subject: [PATCH 243/302] exclude some more versions which just travis does not support --- .travis.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3bb50dc..40f8f23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,11 +24,13 @@ matrix: rvm: 1.9.3 - os: osx rvm: 2.0.0 + - os: linux + rvm: 2.5.0-preview1 - include: - - os: osx - rvm: 1.9.3 - before_script: rvm install ruby-1.9.3 # not binary - - os: osx - rvm: 2.0.0 - before_script: rvm install ruby-2.0.0 # not binary \ No newline at end of file +# include: +# - os: osx +# rvm: 1.9.3 +# before_script: rvm install ruby-1.9.3 # not binary +# - os: osx +# rvm: 2.0.0 +# before_script: rvm install ruby-2.0.0 # not binary \ No newline at end of file From a1562a16e06b389d0f9ab5125180560962cd101d Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 12 Dec 2017 19:46:54 +0300 Subject: [PATCH 244/302] teardown timeout increased --- test-base/test_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-base/test_base.rb b/test-base/test_base.rb index afc3ab3..5fc3523 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -57,7 +57,7 @@ def teardown send_ruby("cont") end debug "Waiting for the server process to finish..." - (config_load('server_start_up_timeout')*4).times do + (config_load('server_start_up_timeout')*5).times do unless @process_finished debug '.' sleep 0.25 From 1280fd49ac75b269708b4fc2b6cb74847242c3a3 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 12 Dec 2017 20:41:05 +0300 Subject: [PATCH 245/302] added one more space at the end of the string to parse --- lib/ruby-debug-ide/commands/expression_info.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/commands/expression_info.rb b/lib/ruby-debug-ide/commands/expression_info.rb index a03bc83..3eccd52 100644 --- a/lib/ruby-debug-ide/commands/expression_info.rb +++ b/lib/ruby-debug-ide/commands/expression_info.rb @@ -9,7 +9,7 @@ def regexp end def execute - string_to_parse = Command.unescape_incoming(@match.post_match) + " \n\n\n" + string_to_parse = Command.unescape_incoming(@match.post_match) + " \n \n\n" total_lines = string_to_parse.count("\n") + 1 lexer = RubyLex.new From b8c820fbc687a7d885a01c935f8669ba22c11cd9 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Thu, 14 Dec 2017 17:58:51 +0300 Subject: [PATCH 246/302] `@test2_path` force encoding to utf-8 --- test-base/test_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-base/test_base.rb b/test-base/test_base.rb index 5fc3523..1caf216 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -141,7 +141,7 @@ def create_file(script_name, lines) def create_test2(lines) @test2_name = "test2.rb" - @test2_path = create_file(@test2_name, lines) + @test2_path = create_file(@test2_name, lines).force_encoding(Encoding::UTF_8) end # Creates test.rb with the given lines, set up @test_name and @test_path From bcaae13730a9b899db09b0e53f623e9212d95340 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Mon, 18 Dec 2017 19:44:29 +0300 Subject: [PATCH 247/302] realpath in file creation added --- test-base/test_base.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test-base/test_base.rb b/test-base/test_base.rb index 1caf216..01bd85d 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -132,7 +132,8 @@ def TestBase.find_free_port(port = 1098) end def create_file(script_name, lines) - script_path = File.join(TMP_DIR, script_name) + script_path = File.realdirpath(File.join(TMP_DIR, script_name)) + File.open(script_path, "w") do |script| script.printf(lines.join("\n")) end From b91656113887c8604e4ed649791a6f689177a2f6 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Mon, 18 Dec 2017 19:57:07 +0300 Subject: [PATCH 248/302] inc debase version in gemfile --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index eff0f6c..2f97c35 100644 --- a/Gemfile +++ b/Gemfile @@ -13,7 +13,7 @@ end gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') if RUBY_VERSION && RUBY_VERSION >= "2.0" - gem "debase", ">= 0.2.2.beta12", :platforms => mries('20', '21', '22', '23', '24', '25') + gem "debase", ">= 0.2.2.beta14", :platforms => mries('20', '21', '22', '23', '24', '25') end gemspec From 6f7703fa561df689c9739b4df9ccbdd367dc1c67 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 20 Dec 2017 14:39:50 +0300 Subject: [PATCH 249/302] bump version --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 3287e97..908fcb2 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta11' + IDE_VERSION='0.6.1.beta12' end From f9a0efd5bc888b2ab5099acbb7803a0473d81a00 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Wed, 6 Dec 2017 19:53:34 +0300 Subject: [PATCH 250/302] deleted check instance has `object_id` method --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index de425f5..49b0b2e 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -279,7 +279,7 @@ def print_variable(name, value, kind) print("", CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, build_value_attr(escaped_value_str), value.class, - has_children, value.respond_to?(:object_id) ? value.object_id : value.id) + has_children, value.object_id) print("", escaped_value_str) if Debugger.value_as_nested_element print('') rescue StandardError => e From d81b309a7c951465e9d27d95bd1eeac762bd3425 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 31 Jan 2018 21:39:44 +0300 Subject: [PATCH 251/302] bump version to 0.6.1 (stable) debase dependency changed to semantic on stable 0.2.2 --- Gemfile | 2 +- lib/ruby-debug-ide/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 2f97c35..9d8626c 100644 --- a/Gemfile +++ b/Gemfile @@ -13,7 +13,7 @@ end gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') if RUBY_VERSION && RUBY_VERSION >= "2.0" - gem "debase", ">= 0.2.2.beta14", :platforms => mries('20', '21', '22', '23', '24', '25') + gem "debase", "~> 0.2.2", :platforms => mries('20', '21', '22', '23', '24', '25') end gemspec diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 908fcb2..41f8b9f 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1.beta12' + IDE_VERSION='0.6.1' end From e0c1bb2f1dbe878f779df6b7d2f7413b43c1b145 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Wed, 31 Jan 2018 21:40:42 +0300 Subject: [PATCH 252/302] add 2.5.0 to travis ruby versions --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 40f8f23..31827b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ rvm: - 2.2.8 - 2.3.5 - 2.4.2 - - 2.5.0-preview1 + - 2.5.0 - ruby-head matrix: @@ -24,8 +24,6 @@ matrix: rvm: 1.9.3 - os: osx rvm: 2.0.0 - - os: linux - rvm: 2.5.0-preview1 # include: # - os: osx From e912ed2834d833ae0b2241b19c05251c0376fe28 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Thu, 1 Feb 2018 11:38:40 +0300 Subject: [PATCH 253/302] set target version to 0.7.0.beta1 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 41f8b9f..ff7fbb7 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.6.1' + IDE_VERSION='0.7.0.beta1' end From 2849d3f8e49a950a4eed357f4788f00e7caf18f1 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 30 Jan 2018 18:36:31 +0300 Subject: [PATCH 254/302] new strategy of notifying the dispatcher (cherry picked from commit f1c9639) --- lib/ruby-debug-ide.rb | 33 ++++++++++++++++---- lib/ruby-debug-ide/greeter.rb | 4 +-- lib/ruby-debug-ide/multiprocess/pre_child.rb | 12 ++----- lib/ruby-debug-ide/version.rb | 2 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 62c0671..7874134 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -18,6 +18,13 @@ module Debugger class << self + def find_free_port(host) + server = TCPServer.open(host, 0) + port = server.addr[1] + server.close + port + end + # Prints to the stderr using printf(*args) if debug logging flag (-d) is on. def print_debug(*args) if Debugger.cli_debug @@ -111,9 +118,15 @@ def start_control(host, port, notify_dispatcher) # 127.0.0.1 seemingly works with all systems and with IPv6 as well. # "localhost" and nil have problems on some systems. host ||= '127.0.0.1' - server = TCPServer.new(host, port) - print_greeting_msg($stderr, host, port) if defined? IDE_VERSION - notify_dispatcher(port) if notify_dispatcher + + server = notify_dispatcher_if_needed(host, port, notify_dispatcher) do |real_port, port_changed = false| + s = TCPServer.new(host, real_port) + print_greeting_msg $stderr, host, real_port, port_changed ? "Subprocess" : "Fast" if defined? IDE_VERSION + s + end + + return unless server + while (session = server.accept) $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug dispatcher = ENV['IDE_PROCESS_DISPATCHER'] @@ -141,8 +154,9 @@ def start_control(host, port, notify_dispatcher) private + def notify_dispatcher_if_needed(host, port, need_notify) + return yield port unless need_notify - def notify_dispatcher(port) return unless 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 @@ -151,11 +165,19 @@ def notify_dispatcher(port) 3.times do |i| begin s = TCPSocket.open(acceptor_host, acceptor_port) + dispatcher_answer = s.gets.chomp + + if dispatcher_answer == "true" + port = Debugger.find_free_port(host) + end + + server = yield port, dispatcher_answer == "true" + s.print(port) s.close connected = true print_debug "Ide process dispatcher notified about sub-debugger which listens on #{port}\n" - return + return server rescue => bt $stderr.puts "#{Process.pid}: connection failed(#{i+1})" $stderr.puts "Exception: #{bt}" @@ -164,7 +186,6 @@ def notify_dispatcher(port) end unless connected end end - end class Exception # :nodoc: diff --git a/lib/ruby-debug-ide/greeter.rb b/lib/ruby-debug-ide/greeter.rb index df9b042..7e3dd93 100644 --- a/lib/ruby-debug-ide/greeter.rb +++ b/lib/ruby-debug-ide/greeter.rb @@ -10,7 +10,7 @@ module Debugger class << self - def print_greeting_msg(stream, host, port) + def print_greeting_msg(stream, host, port, debugger_name = "Fast") base_gem_name = if defined?(JRUBY_VERSION) || RUBY_VERSION < '1.9.0' 'ruby-debug-base' elsif RUBY_VERSION < '2.0.0' @@ -31,7 +31,7 @@ def print_greeting_msg(stream, host, port) listens_on = "\n" end - msg = "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, #{base_gem_name} #{VERSION}, file filtering is #{file_filtering_support})" + listens_on + msg = "#{debugger_name} Debugger (ruby-debug-ide #{IDE_VERSION}, #{base_gem_name} #{VERSION}, file filtering is #{file_filtering_support})" + listens_on stream.printf msg end diff --git a/lib/ruby-debug-ide/multiprocess/pre_child.rb b/lib/ruby-debug-ide/multiprocess/pre_child.rb index 4a349fd..b707fc4 100644 --- a/lib/ruby-debug-ide/multiprocess/pre_child.rb +++ b/lib/ruby-debug-ide/multiprocess/pre_child.rb @@ -11,7 +11,7 @@ def pre_child(options = nil) 'frame_bind' => false, 'host' => host, 'load_mode' => false, - 'port' => find_free_port(host), + 'port' => Debugger.find_free_port(host), 'stop' => false, 'tracing' => false, 'int_handler' => true, @@ -24,7 +24,7 @@ def pre_child(options = nil) ) if(options.ignore_port) - options.port = find_free_port(options.host) + options.port = Debugger.find_free_port(options.host) options.notify_dispatcher = true end @@ -54,14 +54,6 @@ def start_debugger(options) Debugger.cli_debug = options.cli_debug Debugger.prepare_debugger(options) end - - - def find_free_port(host) - server = TCPServer.open(host, 0) - port = server.addr[1] - server.close - port - end end end end \ No newline at end of file diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index ff7fbb7..d14c8d8 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta1' + IDE_VERSION='0.7.0.beta2' end From 0d291b51f4c443133fd481a0e5508eb8017c5ee4 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 4 Aug 2017 20:41:34 +0300 Subject: [PATCH 255/302] set alias for Thread during eval execution (cherry picked from commit 56e1a3f) --- bin/rdebug-ide | 8 ++++++++ lib/ruby-debug-ide/command.rb | 11 ++++++++++- lib/ruby-debug-ide/thread-alias/alias_thread.rb | 2 ++ lib/ruby-debug-ide/thread-alias/unalias_thread.rb | 1 + lib/ruby-debug-ide/thread_alias.rb | 13 +++++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 lib/ruby-debug-ide/thread-alias/alias_thread.rb create mode 100644 lib/ruby-debug-ide/thread-alias/unalias_thread.rb create mode 100644 lib/ruby-debug-ide/thread_alias.rb diff --git a/bin/rdebug-ide b/bin/rdebug-ide index a72dfd1..698564e 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -131,6 +131,14 @@ else Debugger::PROG_SCRIPT = $0 end +if RUBY_VERSION < "1.9" + lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib/") + $: << lib_path unless $:.include? lib_path + require 'ruby-debug-ide/thread_alias.rb' +else + require_relative '../lib/ruby-debug-ide/thread_alias' +end + if options.dispatcher_port != -1 ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s if RUBY_VERSION < "1.9" diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index e6ee3e1..55f96f7 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -128,9 +128,18 @@ def debug_eval(str, b = get_binding) to_inspect = Command.unescape_incoming(str) max_time = Debugger.evaluation_timeout @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time) + + Debugger::TimeoutHandler.do_thread_alias + + eval_result = nil + timeout(max_time) do - eval(to_inspect, b) + eval_result = eval(to_inspect, b) end + + Debugger::TimeoutHandler.undo_thread_alias + + return eval_result rescue StandardError, ScriptError => e @printer.print_exception(e, @state.binding) throw :debug_error diff --git a/lib/ruby-debug-ide/thread-alias/alias_thread.rb b/lib/ruby-debug-ide/thread-alias/alias_thread.rb new file mode 100644 index 0000000..a37eddb --- /dev/null +++ b/lib/ruby-debug-ide/thread-alias/alias_thread.rb @@ -0,0 +1,2 @@ +OldThread = Thread +Thread = Debugger::DebugThread \ No newline at end of file diff --git a/lib/ruby-debug-ide/thread-alias/unalias_thread.rb b/lib/ruby-debug-ide/thread-alias/unalias_thread.rb new file mode 100644 index 0000000..8ead867 --- /dev/null +++ b/lib/ruby-debug-ide/thread-alias/unalias_thread.rb @@ -0,0 +1 @@ +Thread = OldThread \ No newline at end of file diff --git a/lib/ruby-debug-ide/thread_alias.rb b/lib/ruby-debug-ide/thread_alias.rb new file mode 100644 index 0000000..1cc38d4 --- /dev/null +++ b/lib/ruby-debug-ide/thread_alias.rb @@ -0,0 +1,13 @@ +module Debugger + module TimeoutHandler + class << self + def do_thread_alias + load File.expand_path(File.dirname(__FILE__) + '/thread-alias/alias_thread.rb') + end + + def undo_thread_alias + load File.expand_path(File.dirname(__FILE__) + '/thread-alias/unalias_thread.rb') + end + end + end +end \ No newline at end of file From 01219cea969058c0ab95e59aecb28e56a79a3ee0 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Sun, 11 Mar 2018 19:25:41 +0300 Subject: [PATCH 256/302] add tests for thread aliasing Covering commit 0d291b51f4c443133fd481a0e5508eb8017c5ee4. --- test-base/inspect_test.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test-base/inspect_test.rb b/test-base/inspect_test.rb index ca57de8..c130bc0 100644 --- a/test-base/inspect_test.rb +++ b/test-base/inspect_test.rb @@ -58,6 +58,26 @@ def test_inspect_error_2 send_cont end + def test_inspect_expr_with_timeout + create_socket ["require 'timeout'", "puts 'test'"] + run_to_line(2) + send_ruby("v inspect (Timeout::timeout(10) { nil })") + variables = read_variables + assert_equal(1, variables.length, "There is one variable returned which is nil.") + assert_equal(nil, variables[0].value) + send_cont + end + + def test_inspect_failing_expr_with_timeout + create_socket ["require 'timeout'", "puts 'test'"] + run_to_line(2) + send_ruby("v inspect (Timeout::timeout(0.1) { sleep 0.2 })") + variables = read_variables + assert_equal(1, variables.length, "There is one variable returned which is nil.") + assert_equal("Timeout::Error", variables[0].type) + send_cont + end + def test_inspect_multiline_expression create_socket ["sleep 0.1"] run_to_line(1) From 5bca348f14ca36623e83c53823ef4aa6270b9ee0 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Sun, 11 Mar 2018 19:36:27 +0300 Subject: [PATCH 257/302] #137 fix warnings on thread aliasing --- .../thread-alias/alias_thread.rb | 2 -- .../thread-alias/unalias_thread.rb | 1 - lib/ruby-debug-ide/thread_alias.rb | 18 ++++++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) delete mode 100644 lib/ruby-debug-ide/thread-alias/alias_thread.rb delete mode 100644 lib/ruby-debug-ide/thread-alias/unalias_thread.rb diff --git a/lib/ruby-debug-ide/thread-alias/alias_thread.rb b/lib/ruby-debug-ide/thread-alias/alias_thread.rb deleted file mode 100644 index a37eddb..0000000 --- a/lib/ruby-debug-ide/thread-alias/alias_thread.rb +++ /dev/null @@ -1,2 +0,0 @@ -OldThread = Thread -Thread = Debugger::DebugThread \ No newline at end of file diff --git a/lib/ruby-debug-ide/thread-alias/unalias_thread.rb b/lib/ruby-debug-ide/thread-alias/unalias_thread.rb deleted file mode 100644 index 8ead867..0000000 --- a/lib/ruby-debug-ide/thread-alias/unalias_thread.rb +++ /dev/null @@ -1 +0,0 @@ -Thread = OldThread \ No newline at end of file diff --git a/lib/ruby-debug-ide/thread_alias.rb b/lib/ruby-debug-ide/thread_alias.rb index 1cc38d4..4e10a7b 100644 --- a/lib/ruby-debug-ide/thread_alias.rb +++ b/lib/ruby-debug-ide/thread_alias.rb @@ -2,11 +2,25 @@ module Debugger module TimeoutHandler class << self def do_thread_alias - load File.expand_path(File.dirname(__FILE__) + '/thread-alias/alias_thread.rb') + if defined? ::OldThread + Debugger.print_debug 'Tried to re-alias thread for eval' + return + end + + Object.const_set :OldThread, ::Thread + Object.send :remove_const, :Thread + Object.const_set :Thread, ::Debugger::DebugThread end def undo_thread_alias - load File.expand_path(File.dirname(__FILE__) + '/thread-alias/unalias_thread.rb') + unless defined? ::OldThread + Debugger.print_debug 'Tried to de-alias thread twice' + return + end + + Object.send :remove_const, :Thread + Object.const_set :Thread, ::OldThread + Object.send :remove_const, :OldThread end end end From bd9f77aa93b7d1dd7352576f7ddef43311cc6cb1 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 13 Mar 2018 16:12:20 +0300 Subject: [PATCH 258/302] bump version to beta3 [ci skip] --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index d14c8d8..36552ae 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta2' + IDE_VERSION='0.7.0.beta3' end From badd1054a7f2f3f82722083f0c06a90d52081a9e Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Mon, 26 Mar 2018 13:39:32 +0300 Subject: [PATCH 259/302] require thread_alias in caller (#141) --- bin/rdebug-ide | 8 -------- lib/ruby-debug-ide/command.rb | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 698564e..a72dfd1 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -131,14 +131,6 @@ else Debugger::PROG_SCRIPT = $0 end -if RUBY_VERSION < "1.9" - lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib/") - $: << lib_path unless $:.include? lib_path - require 'ruby-debug-ide/thread_alias.rb' -else - require_relative '../lib/ruby-debug-ide/thread_alias' -end - if options.dispatcher_port != -1 ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s if RUBY_VERSION < "1.9" diff --git a/lib/ruby-debug-ide/command.rb b/lib/ruby-debug-ide/command.rb index 55f96f7..ecbd2ba 100644 --- a/lib/ruby-debug-ide/command.rb +++ b/lib/ruby-debug-ide/command.rb @@ -4,6 +4,7 @@ require 'debase' end +require 'ruby-debug-ide/thread_alias' require 'ruby-debug-ide/helper' require 'delegate' From d171ee2d1522a6ce73afb2600b4aa917ce6304ff Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Tue, 27 Mar 2018 20:11:38 +0300 Subject: [PATCH 260/302] bump version to beta4 [ci skip] --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 36552ae..8524da7 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta3' + IDE_VERSION='0.7.0.beta4' end From 91ff6d7d1660ef74c74399d38f39eed82002b45e Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 23 Mar 2018 19:28:24 +0300 Subject: [PATCH 261/302] check if block given before yield in xml's print_element --- lib/ruby-debug-ide/xml_printer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 49b0b2e..916f33a 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -442,7 +442,7 @@ def print_load_result(file, exception = nil) def print_element(name) print("<#{name}>") begin - yield + yield if block_given? ensure print("") end From 421fb009c3eade2b13c372e578adc3989827db6f Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Mon, 4 Jun 2018 20:13:39 +0300 Subject: [PATCH 262/302] new hash item presentation, lets add objectId of a hash key to the xml so we can inspect it later --- bin/rdebug-ide | 7 +++- lib/ruby-debug-ide.rb | 1 + lib/ruby-debug-ide/xml_printer.rb | 32 +++++++++++--- test-base/test_base.rb | 8 ++-- test-base/variables_test.rb | 70 ++++++++++++++++++++++++------- test/rd_test_base.rb | 4 +- 6 files changed, 96 insertions(+), 26 deletions(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index a72dfd1..3054353 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -27,7 +27,8 @@ options = OpenStruct.new( 'catchpoint_deleted_event' => false, 'value_as_nested_element' => false, 'attach_mode' => false, - 'cli_debug' => false + 'cli_debug' => false, + 'key_value_mode' => false ) opts = OptionParser.new do |opts| @@ -80,6 +81,9 @@ EOB opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do options.attach_mode = true end + opts.on("--key-value", "Key/Value presentation of hash items") do + options.key_value_mode = true + end opts.on("--ignore-port", "Generate another port") do options.ignore_port = true end @@ -166,6 +170,7 @@ Debugger.debugger_memory_limit = options.debugger_memory_limit Debugger.inspect_time_limit = options.inspect_time_limit Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions +Debugger.key_value_mode = options.key_value_mode if options.attach_mode if Debugger::FRONT_END == "debase" diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 7874134..e7b57d4 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -51,6 +51,7 @@ def cleanup_backtrace(backtrace) end attr_accessor :attached + attr_accessor :key_value_mode attr_accessor :cli_debug, :xml_debug, :evaluation_timeout attr_accessor :trace_to_s, :debugger_memory_limit, :inspect_time_limit attr_accessor :control_thread diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 916f33a..65b8dbf 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -144,19 +144,36 @@ def print_array(array) end end - def print_hash(hash) + def do_print_hash_key_value(hash) + print_element("variables", {:type => 'hashItem'}) do + hash.each {|(k, v)| + print_variable('key', k, 'instance') + print_variable('value', v, 'instance') + } + end + end + + def do_print_hash(hash) print_element("variables") do - hash.keys.each {|k| + hash.each {|(k, v)| if k.class.name == "String" name = '\'' + k + '\'' else name = exec_with_allocation_control(k, :to_s, OverflowMessageType::EXCEPTION_MESSAGE) end - print_variable(name, hash[k], 'instance') + print_variable(name, v, 'instance') } end end + def print_hash(hash) + if Debugger.key_value_mode + do_print_hash_key_value(hash) + else + do_print_hash(hash) + end + end + def print_string(string) print_element("variables") do if string.respond_to?('bytes') @@ -243,6 +260,7 @@ def exec_with_allocation_control(value, exec_method, overflow_message_type) def print_variable(name, value, kind) name = name.to_s + if value.nil? print("", CGI.escapeHTML(name), kind) return @@ -280,6 +298,7 @@ def print_variable(name, value, kind) CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind, build_value_attr(escaped_value_str), value.class, has_children, value.object_id) + print("", escaped_value_str) if Debugger.value_as_nested_element print('') rescue StandardError => e @@ -439,8 +458,11 @@ def print_load_result(file, exception = nil) end end - def print_element(name) - print("<#{name}>") + def print_element(name, additional_tags = nil) + additional_tags_presentation = additional_tags.nil? ? '' + : additional_tags.map {|tag, value| " #{tag}=\"#{value}\""}.reduce(:+) + + print("<#{name}#{additional_tags_presentation}>") begin yield if block_given? ensure diff --git a/test-base/test_base.rb b/test-base/test_base.rb index 01bd85d..91cf22d 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -82,9 +82,9 @@ def debug_jruby? config_load('debug_jruby') end - def start_ruby_process(script) + def start_ruby_process(script, additional_opts = '') @port = TestBase.find_free_port - cmd = debug_command(script, @port) + cmd = debug_command(script, @port, additional_opts) debug "Starting: #{cmd}\n" Thread.new do @@ -147,10 +147,10 @@ def create_test2(lines) # Creates test.rb with the given lines, set up @test_name and @test_path # variables and then start the process. - def create_socket(lines) + def create_socket(lines, additional_opts = '') @test_name = "test.rb" @test_path = create_file(@test_name, lines) - start_ruby_process(@test_path) + start_ruby_process(@test_path, additional_opts) end def socket diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 67f9b48..50c1b2d 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -199,22 +199,64 @@ def test_to_s_raises_exception send_cont end + def test_new_hash_presentation + create_socket ['class A', + ' def to_s', + ' "A instance"', + ' end', + 'end', + + 'class C', + ' def to_s', + ' "C instance"', + ' end', + 'end', + + 'b = Hash.new', + 'c = C.new', + 'a = A.new', + 'b[1] = a', + 'b[a] = "1"', + 'b[c] = a', + 'puts b #bp here'], '--key-value' + run_to_line(17) + send_ruby('v l') + assert_variables(read_variables, 3, + {:name => "a", :value => "A instance",:type => "A"}, + {:name => "b", :value => "Hash (3 elements)", :type => "Hash"}, + {:name => "c", :value => "C instance", :type => "C"}) + + send_ruby("v i b") + + assert_variables(read_variables, 6, + {:name => "key", :value => "1"}, + {:name => "value", :value => "A instance", :type => "A"}, + + {:name => "key", :value => "A instance", :type => "A"}, + {:name => "value", :value => "1", :type => "String"}, + + {:name => "key", :value => "C instance", :type => "C"}, + {:name => "value", :value => "A instance", :type => "A"}) + send_cont + end + def test_to_s_timelimit create_socket ['class A', - 'def to_s', - 'a = 1', - 'loop do', - 'a = a + 1', - 'sleep 1', - 'break if (a > 2)', - 'end', - 'a.to_s', - 'end', - 'end', - 'b = Hash.new', - 'b[A.new] = A.new', - 'b[1] = A.new', - 'puts b #bp here'] + 'def to_s', + 'a = 1', + 'loop do', + 'a = a + 1', + 'sleep 1', + 'break if (a > 2)', + 'end', + 'a.to_s', + 'end', + 'end', + + 'b = Hash.new', + 'b[A.new] = A.new', + 'b[1] = A.new', + 'puts b #bp here'], '--evaluation-control --time-limit 100 --memory-limit 0' run_to_line(15) send_ruby('v l') assert_variables(read_variables, 1, diff --git a/test/rd_test_base.rb b/test/rd_test_base.rb index 7d29edc..d5b7e4f 100644 --- a/test/rd_test_base.rb +++ b/test/rd_test_base.rb @@ -18,13 +18,13 @@ def setup end end - def debug_command(script, port) + def debug_command(script, port, additional_opts='') cmd = "#{interpreter}" cmd << " --debug" if jruby? cmd << " -J-Xdebug -J-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y" if jruby? and debug_jruby? cmd << " -I 'lib:#{File.dirname(script)}' #{@rdebug_ide}" + (@verbose_server ? " -d" : "") + - " -p #{port} --evaluation-control --time-limit 100 --memory-limit 0 -- '#{script}'" + " -p #{port} #{additional_opts} -- '#{script}'" end def start_debugger From bff361864ff4a99296dd0177209193e3fb85a770 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Wed, 13 Jun 2018 17:53:14 +0300 Subject: [PATCH 263/302] notify debugger about gdb_wrapper pid to kill it when debugging finished (#149) --- bin/gdb_wrapper | 5 ++++- bin/rdebug-ide | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index a439204..2442036 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -65,7 +65,10 @@ unless options.ruby_path exit 1 end -argv = '["' + ARGV * '", "' + '"]' +main_process_argv = ARGV +main_process_argv << '--gdb-wrapper-pid' << "#{Process.pid}" +argv = '["' + main_process_argv * '", "' + '"]' + child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]' debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 3054353..1a244bd 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -28,6 +28,7 @@ options = OpenStruct.new( 'value_as_nested_element' => false, 'attach_mode' => false, 'cli_debug' => false, + 'gdb_wrapper_pid' => nil, 'key_value_mode' => false ) @@ -43,6 +44,8 @@ EOB opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} + opts.on("-gdbp", "--gdb-wrapper-pid PID", Integer, "Pid of corresponding gdb_wrapper (for attach case)") {|pid| options.gdb_wrapper_pid = pid} + opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| options.dispatcher_port = dp end @@ -173,6 +176,7 @@ Debugger.value_as_nested_element = options.value_as_nested_element || options.rm Debugger.key_value_mode = options.key_value_mode if options.attach_mode + at_exit {Process.kill('INT', options.gdb_wrapper_pid)} if options.gdb_wrapper_pid if Debugger::FRONT_END == "debase" Debugger.init_variables end From da167dbda47dd91db058f5e5fb2810dd6a585034 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 18 Jun 2018 19:36:53 +0300 Subject: [PATCH 264/302] bump version to 0.7.0.beta5 [ci skip] --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 8524da7..9b16003 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta4' + IDE_VERSION='0.7.0.beta5' end From b4c8f15cb4ad48b636a381757363e9a3d705baf5 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Thu, 21 Jun 2018 18:09:36 +0300 Subject: [PATCH 265/302] fix debase dependency version to accept 2.3, too (#150) --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 9d8626c..3f1837e 100644 --- a/Gemfile +++ b/Gemfile @@ -13,7 +13,7 @@ end gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') if RUBY_VERSION && RUBY_VERSION >= "2.0" - gem "debase", "~> 0.2.2", :platforms => mries('20', '21', '22', '23', '24', '25') + gem "debase", "~> 0.2", ">= 0.2.2", :platforms => mries('20', '21', '22', '23', '24', '25') end gemspec From 235f8fa86b23295f23b4f7894b2ec3418da73e3e Mon Sep 17 00:00:00 2001 From: Geunwoo Shin Date: Fri, 6 Jul 2018 11:23:13 +0900 Subject: [PATCH 266/302] Fixed syntax error on ruby 1.8 --- lib/ruby-debug-ide.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index e7b57d4..10f70f4 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -120,7 +120,7 @@ def start_control(host, port, notify_dispatcher) # "localhost" and nil have problems on some systems. host ||= '127.0.0.1' - server = notify_dispatcher_if_needed(host, port, notify_dispatcher) do |real_port, port_changed = false| + server = notify_dispatcher_if_needed(host, port, notify_dispatcher) do |real_port, port_changed| s = TCPServer.new(host, real_port) print_greeting_msg $stderr, host, real_port, port_changed ? "Subprocess" : "Fast" if defined? IDE_VERSION s From 45b6f400bdad8ba32f6702b89eb4bebb71bf47c3 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 10 Jul 2018 15:25:41 +0300 Subject: [PATCH 267/302] Revert "notify debugger about gdb_wrapper pid to kill it when debugging finished (#149)" This reverts commit bff3618 --- bin/gdb_wrapper | 5 +---- bin/rdebug-ide | 4 ---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/bin/gdb_wrapper b/bin/gdb_wrapper index 2442036..a439204 100755 --- a/bin/gdb_wrapper +++ b/bin/gdb_wrapper @@ -65,10 +65,7 @@ unless options.ruby_path exit 1 end -main_process_argv = ARGV -main_process_argv << '--gdb-wrapper-pid' << "#{Process.pid}" -argv = '["' + main_process_argv * '", "' + '"]' - +argv = '["' + ARGV * '", "' + '"]' child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]' debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader' diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 1a244bd..3054353 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -28,7 +28,6 @@ options = OpenStruct.new( 'value_as_nested_element' => false, 'attach_mode' => false, 'cli_debug' => false, - 'gdb_wrapper_pid' => nil, 'key_value_mode' => false ) @@ -44,8 +43,6 @@ EOB opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host} opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port} - opts.on("-gdbp", "--gdb-wrapper-pid PID", Integer, "Pid of corresponding gdb_wrapper (for attach case)") {|pid| options.gdb_wrapper_pid = pid} - opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp| options.dispatcher_port = dp end @@ -176,7 +173,6 @@ Debugger.value_as_nested_element = options.value_as_nested_element || options.rm Debugger.key_value_mode = options.key_value_mode if options.attach_mode - at_exit {Process.kill('INT', options.gdb_wrapper_pid)} if options.gdb_wrapper_pid if Debugger::FRONT_END == "debase" Debugger.init_variables end From 103a1a25e253bae0c686055f8a8ebdfec8378501 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 10 Jul 2018 15:56:40 +0300 Subject: [PATCH 268/302] bump ruby-debug-ide version to 0.7.0.beta6 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 9b16003..c47f24f 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta5' + IDE_VERSION='0.7.0.beta6' end From bc1bd1dc46a0a154957e8959e24d49e276bd6c07 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 17 Jul 2018 16:17:37 +0300 Subject: [PATCH 269/302] linux 1.8.7 added to travis --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 31827b8..e2f2db4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ os: - osx rvm: + - 1.8.7 - 1.9.3 - 2.0.0 - 2.1.10 @@ -25,6 +26,9 @@ matrix: - os: osx rvm: 2.0.0 + - os: osx + rvm: 1.8.7 + # include: # - os: osx # rvm: 1.9.3 From 4c60264483b49e9495649d60f84d52e6fec29344 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 17 Jul 2018 16:18:02 +0300 Subject: [PATCH 270/302] old ruby doesn't support multiline commands --- lib/ruby-debug-ide/xml_printer.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ruby-debug-ide/xml_printer.rb b/lib/ruby-debug-ide/xml_printer.rb index 65b8dbf..416be25 100644 --- a/lib/ruby-debug-ide/xml_printer.rb +++ b/lib/ruby-debug-ide/xml_printer.rb @@ -459,8 +459,7 @@ def print_load_result(file, exception = nil) end def print_element(name, additional_tags = nil) - additional_tags_presentation = additional_tags.nil? ? '' - : additional_tags.map {|tag, value| " #{tag}=\"#{value}\""}.reduce(:+) + additional_tags_presentation = additional_tags.nil? ? '' : additional_tags.map {|tag, value| " #{tag}=\"#{value}\""}.reduce(:+) print("<#{name}#{additional_tags_presentation}>") begin From ad80334f236f530e9fb44c261c18dbc6f822604b Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 17 Jul 2018 16:19:31 +0300 Subject: [PATCH 271/302] tests reworked to work on 1.8.7 --- test-base/inspect_test.rb | 4 ++++ test-base/test_base.rb | 9 ++++++--- test-base/variables_test.rb | 20 +++++++++++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/test-base/inspect_test.rb b/test-base/inspect_test.rb index c130bc0..c7ff66b 100644 --- a/test-base/inspect_test.rb +++ b/test-base/inspect_test.rb @@ -69,6 +69,10 @@ def test_inspect_expr_with_timeout end def test_inspect_failing_expr_with_timeout + if RUBY_VERSION < "1.9" + @process_finished = true + return + end create_socket ["require 'timeout'", "puts 'test'"] run_to_line(2) send_ruby("v inspect (Timeout::timeout(0.1) { sleep 0.2 })") diff --git a/test-base/test_base.rb b/test-base/test_base.rb index 91cf22d..c026750 100644 --- a/test-base/test_base.rb +++ b/test-base/test_base.rb @@ -132,8 +132,9 @@ def TestBase.find_free_port(port = 1098) end def create_file(script_name, lines) - script_path = File.realdirpath(File.join(TMP_DIR, script_name)) - + file = File.join(TMP_DIR, script_name) + script_path = RUBY_VERSION >= "1.9" ? File.realdirpath(file) : file.to_s + File.open(script_path, "w") do |script| script.printf(lines.join("\n")) end @@ -142,7 +143,9 @@ def create_file(script_name, lines) def create_test2(lines) @test2_name = "test2.rb" - @test2_path = create_file(@test2_name, lines).force_encoding(Encoding::UTF_8) + @test2_path = create_file(@test2_name, lines) + + @test2_path = @test2_path.force_encoding(Encoding::UTF_8) if RUBY_VERSION >= "1.9" end # Creates test.rb with the given lines, set up @test_name and @test_path diff --git a/test-base/variables_test.rb b/test-base/variables_test.rb index 50c1b2d..85a44b3 100644 --- a/test-base/variables_test.rb +++ b/test-base/variables_test.rb @@ -100,7 +100,9 @@ def test_variable_local end def test_variable_instance - create_socket ["require_relative 'test2.rb'", "custom_object=Test2.new", "puts custom_object"] + require_string = RUBY_VERSION < "1.9" ? "require" : "require_relative" + + create_socket ["#{require_string} 'test2.rb'", "custom_object=Test2.new", "puts custom_object"] create_test2 ["class Test2", "def initialize", "@y=5", "end", "def to_s", "'test'", "end", "end"] run_to("test2.rb", 6) frame_number = 3 @@ -130,8 +132,9 @@ def test_variable_hash_with_string_keys assert_variables(read_variables, 1, {:name => "hash", :hasChildren => true}) send_ruby("v i hash") + expected_name = CGI::escapeHTML("'a'") assert_variables(read_variables, 2, - {:name => CGI.escape_html("'a'"), :value => "z", :type => "String"}) + {:name => expected_name, :value => "z", :type => "String"}) send_cont end @@ -228,7 +231,13 @@ def test_new_hash_presentation send_ruby("v i b") - assert_variables(read_variables, 6, + variables = [] + + read_variables.each_slice(2) do |var| + variables << var + end + + assert_variables(variables.sort_by{|a| a[0].value}.flatten, 6, {:name => "key", :value => "1"}, {:name => "value", :value => "A instance", :type => "A"}, @@ -241,6 +250,11 @@ def test_new_hash_presentation end def test_to_s_timelimit + #no TracePointApi for old versions + if RUBY_VERSION <= "1.9" + @process_finished = true + return + end create_socket ['class A', 'def to_s', 'a = 1', From 694f1a06856d66ca67a3e32fc505fa9fec545a7c Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 17 Jul 2018 16:20:27 +0300 Subject: [PATCH 272/302] gemfile reworked to work on old ruby versions --- Gemfile | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 3f1837e..c8e7b16 100644 --- a/Gemfile +++ b/Gemfile @@ -3,15 +3,19 @@ source "http://rubygems.org/" # @param [Array] versions compatible ruby versions # @return [Array] an array with mri platforms of given versions def mries(*versions) - versions.flat_map do |v| - %w(ruby mingw x64_mingw) - .map { |platform| "#{platform}_#{v}".to_sym unless platform == "x64_mingw" && v < "2.0" } - .delete_if &:nil? - end + versions.map do |v| + %w(ruby mingw x64_mingw).map do |platform| + "#{platform}_#{v}".to_sym unless platform == "x64_mingw" && v < "2.0" + end.delete_if &:nil? + end.flatten +end + +gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] + +if RUBY_VERSION && RUBY_VERSION >= "1.9" + gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') end -gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] -gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') if RUBY_VERSION && RUBY_VERSION >= "2.0" gem "debase", "~> 0.2", ">= 0.2.2", :platforms => mries('20', '21', '22', '23', '24', '25') end @@ -23,6 +27,10 @@ group :development do end group :test do - gem "test-unit" + if RUBY_VERSION < "1.9" + gem "test-unit", "~> 2.1.2" + else + gem "test-unit" + end end From 7b5d00be148a15d7bb4f59741b199b56449602d5 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 17 Jul 2018 16:43:34 +0300 Subject: [PATCH 273/302] bump version to 0.7.0.beta7 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index c47f24f..6bcc59e 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta6' + IDE_VERSION='0.7.0.beta7' end From ab971e6097a41267e17418d4879698d33719650f Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Wed, 18 Jul 2018 14:56:35 +0300 Subject: [PATCH 274/302] gemfile ruby-debug-base case --- Gemfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index c8e7b16..c36df53 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,9 @@ def mries(*versions) end.flatten end -gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] +if RUBY_VERSION < '1.9' || defined?(JRUBY_VERSION) + gem "ruby-debug-base", :platforms => [:jruby, *mries('18')] +end if RUBY_VERSION && RUBY_VERSION >= "1.9" gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19') From 1a93fbc01449ccc34e5f7738a2d2a10a99e3fb8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Rodrigues?= Date: Tue, 19 Feb 2019 14:55:19 -0300 Subject: [PATCH 275/302] Removed deprecation warning message --- ruby-debug-ide.gemspec | 3 --- 1 file changed, 3 deletions(-) diff --git a/ruby-debug-ide.gemspec b/ruby-debug-ide.gemspec index 7cd29ef..47af820 100644 --- a/ruby-debug-ide.gemspec +++ b/ruby-debug-ide.gemspec @@ -45,7 +45,4 @@ EOF spec.required_ruby_version = '>= 1.8.2' spec.date = DateTime.now spec.rubyforge_project = 'debug-commons' - - # rdoc - spec.has_rdoc = false end From 8c29caa57cd03f484c8d92b221dc6f398099d19b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Rodrigues?= Date: Tue, 19 Feb 2019 14:56:40 -0300 Subject: [PATCH 276/302] Added option to skip waitting for start --- bin/rdebug-ide | 2 ++ lib/ruby-debug-ide.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/rdebug-ide b/bin/rdebug-ide index 3054353..618e291 100755 --- a/bin/rdebug-ide +++ b/bin/rdebug-ide @@ -17,6 +17,7 @@ options = OpenStruct.new( 'port' => 1234, 'stop' => false, 'tracing' => false, + 'skip_wait_for_start' => false, 'int_handler' => true, 'dispatcher_port' => -1, 'evaluation_timeout' => 10, @@ -67,6 +68,7 @@ EOB opts.on('--stop', 'stop when the script is loaded') {options.stop = true} opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true} + opts.on("--skip_wait_for_start", "skip wait for 'start' command") {options.skip_wait_for_start = true} opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true} opts.on("-d", "--debug", "Debug self - prints information for debugging ruby-debug itself") do Debugger.cli_debug = true diff --git a/lib/ruby-debug-ide.rb b/lib/ruby-debug-ide.rb index 10f70f4..97644df 100644 --- a/lib/ruby-debug-ide.rb +++ b/lib/ruby-debug-ide.rb @@ -90,7 +90,7 @@ def prepare_debugger(options) # wait for 'start' command @mutex.synchronize do @proceed.wait(@mutex) - end + end unless options.skip_wait_for_start end def debug_program(options) From 28c3385707c7d60993ffd61c33fef3f202fdfe94 Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Fri, 23 Mar 2018 01:09:51 +0300 Subject: [PATCH 277/302] check if debase installed (already_installed doesn't work) --- ext/mkrf_conf.rb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ext/mkrf_conf.rb b/ext/mkrf_conf.rb index c8170ac..ece549f 100644 --- a/ext/mkrf_conf.rb +++ b/ext/mkrf_conf.rb @@ -1,11 +1,6 @@ jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE) rbx = defined?(RUBY_ENGINE) && 'rbx' == RUBY_ENGINE -def already_installed(dep) - !Gem::DependencyInstaller.new(:domain => :local).find_gems_with_sources(dep).empty? || - !Gem::DependencyInstaller.new(:domain => :local,:prerelease => true).find_gems_with_sources(dep).empty? -end - unless jruby || rbx require 'rubygems' require 'rubygems/command.rb' @@ -14,14 +9,14 @@ def already_installed(dep) begin Gem::Command.build_args = ARGV - rescue NoMethodError + rescue NoMethodError end if RUBY_VERSION < "1.9" dep = Gem::Dependency.new("ruby-debug-base", '>=0.10.4') elsif RUBY_VERSION < '2.0' dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.30.pre15') - else + else dep = Gem::Dependency.new("debase", '> 0') end @@ -38,7 +33,7 @@ def already_installed(dep) puts e.backtrace.join "\n " exit(1) end - end unless dep.nil? || already_installed(dep) + end unless dep.nil? || dep.matching_specs.any? end # create dummy rakefile to indicate success From cae6dd65bedd182355281370dcc5d44ab4912cba Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Fri, 7 Jun 2019 16:12:57 +0300 Subject: [PATCH 278/302] update ruby version matrix in travis config --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index e2f2db4..15a86ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,10 @@ rvm: - 2.0.0 - 2.1.10 - 2.2.8 - - 2.3.5 - - 2.4.2 - - 2.5.0 + - 2.3.8 + - 2.4.6 + - 2.5.5 + - 2.6.3 - ruby-head matrix: @@ -35,4 +36,4 @@ matrix: # before_script: rvm install ruby-1.9.3 # not binary # - os: osx # rvm: 2.0.0 -# before_script: rvm install ruby-2.0.0 # not binary \ No newline at end of file +# before_script: rvm install ruby-2.0.0 # not binary From d051a4d9c58c64832849106296c068aa24501ce6 Mon Sep 17 00:00:00 2001 From: Alexandr Evstigneev Date: Fri, 7 Jun 2019 16:16:26 +0300 Subject: [PATCH 279/302] Install dependencies into the same root as debugger itself (#172) * Install dependencies into the same root as debugger itself Helps with --user-install on system ruby --- ext/mkrf_conf.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/mkrf_conf.rb b/ext/mkrf_conf.rb index c8170ac..478dca6 100644 --- a/ext/mkrf_conf.rb +++ b/ext/mkrf_conf.rb @@ -1,3 +1,4 @@ +install_dir = File.expand_path("../../../..", __FILE__) jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE) rbx = defined?(RUBY_ENGINE) && 'rbx' == RUBY_ENGINE @@ -27,11 +28,11 @@ def already_installed(dep) begin puts "Installing base gem" - inst = Gem::DependencyInstaller.new :prerelease => dep.prerelease? + inst = Gem::DependencyInstaller.new(:prerelease => dep.prerelease?, :install_dir => install_dir) inst.install dep rescue begin - inst = Gem::DependencyInstaller.new(:prerelease => true) + inst = Gem::DependencyInstaller.new(:prerelease => true, :install_dir => install_dir) inst.install dep rescue Exception => e puts e From b4aff0d9c102309bc9e84787b76a416c80eeb402 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 8 Apr 2019 13:58:45 +0300 Subject: [PATCH 280/302] bump version to 0.7.0 --- lib/ruby-debug-ide/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ruby-debug-ide/version.rb b/lib/ruby-debug-ide/version.rb index 6bcc59e..43d918b 100755 --- a/lib/ruby-debug-ide/version.rb +++ b/lib/ruby-debug-ide/version.rb @@ -1,3 +1,3 @@ module Debugger - IDE_VERSION='0.7.0.beta7' + IDE_VERSION='0.7.0' end From 37d0a64ffbe92245b142c4e06a09ca6de79d1cae Mon Sep 17 00:00:00 2001 From: Viuginov Nickolay Date: Tue, 2 Jul 2019 15:59:45 +0300 Subject: [PATCH 281/302] [RUBY-23972] Improve ruby-debug-ide documentation --- README.md | 33 +++- protocol-spec.md | 406 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 435 insertions(+), 4 deletions(-) create mode 100644 protocol-spec.md diff --git a/README.md b/README.md index d0522d6..0125c3b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,32 @@ -[gem]: https://rubygems.org/gems/ruby-debug-ide -# ruby-debug-ide -An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine. - [![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![Gem Version](https://badge.fury.io/rb/ruby-debug-ide.svg)][gem] [![Build Status](https://travis-ci.org/ruby-debug/ruby-debug-ide.svg?branch=master)](https://travis-ci.org/ruby-debug/ruby-debug-ide) + +[gem]: https://rubygems.org/gems/ruby-debug-ide +# ruby-debug-ide + +The 'ruby-debug-ide' gem provides the protocol to establish communication between the debugger engine (such as [debase](https://rubygems.org/gems/debase) or [ruby-debug-base](https://rubygems.org/gems/ruby-debug-base)) and IDEs (for example, RubyMine, Visual Studio Code, or Eclipse). 'ruby-debug-ide' redirect commands from the IDE to the debugger engine. Then, it returns answers/events received from the debugger engine to the IDE. To learn more about a communication protocol, see the following document: [ruby-debug-ide protocol](protocol-spec.md). + +## Install debugging gems +Depending on the used Ruby version, you need to add/install the following debugging gems to the Gemfile: +- Ruby 2.x - [ruby-debug-ide](https://rubygems.org/gems/ruby-debug-ide) and [debase](https://rubygems.org/gems/debase) +- Ruby 1.9.x - [ruby-debug-ide](https://rubygems.org/gems/ruby-debug-ide) and [ruby-debug-base19x](https://rubygems.org/gems/ruby-debug-base19x) +- jRuby or Ruby 1.8.x - [ruby-debug-ide](https://rubygems.org/gems/ruby-debug-ide) and [ruby-debug-base](https://rubygems.org/gems/ruby-debug-base) +> For Windows, make sure that the Ruby [DevKit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit) is installed. + +## Start debugging session +To start the debugging session for a Rails application, run the following command: +```shell +rdebug-ide --host 0.0.0.0 --port 1234 --dispatcher-port 1234 -- bin/rails s +``` +If you want to debug a Rails application run using Docker Compose, you need to start the Rails server from the Docker in the following way: +```yaml +command: bundle exec rdebug-ide --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b 0.0.0.0 +volumes: + - .:/sample_rails_app +ports: + - "1234:1234" + - "3000:3000" + - "26162:26162" +``` +Note that all ports above should be exposed in the Dockerfile. \ No newline at end of file diff --git a/protocol-spec.md b/protocol-spec.md new file mode 100644 index 0000000..b6f42c0 --- /dev/null +++ b/protocol-spec.md @@ -0,0 +1,406 @@ +ruby-debug-ide protocol +======================= + +* * * + +Next: [Summary](#Summary), Previous: [(dir)](#dir), Up: [(dir)](#dir) + +_ruby-debug-ide_ protocol +------------------------- + +This file contains specification of the protocol used by _ruby-debug-ide_. + +* [Summary](#Summary) +* [Specification](#Specification) +* [Changes](#Changes) + +* * * + +Next: [Specification](#Specification), Previous: [Top](#Top), Up: [Top](#Top) + +1 Summary +--------- + +This document describes protocol used by _ruby-debug-ide_ for communication between debugger engine and a frontend. It is a work in progress and might, and very likely will, change in the future. If you have any comments or questions please [send me](mailto:martin.krauskopf@gmail.com) an email. + +The communication has two parts/sides. First ones are _commands_ sent from a frontend to the debugger engine and the second is the opposite way, _answers_ and _events_ sent from the debugger engine to the frontend. + +_commands_ are almost the same as the ones used by CLI ruby-debug. So you might want to contact [the _ruby-debug-ide_ document](http://bashdb.sourceforge.net/ruby-debug.html). + +_answers_ and _events_ are sent in XML format described in the specification [below](#Specification). + +**Specification is far from complete.** Will be completed as time permits. In the meantime, source code is always the best spec. + +* * * + +Next: [Changes](#Changes), Previous: [Summary](#Summary), Up: [Top](#Top) + +2 Specification +--------------- + +* [Commands](#Commands) +* [Events](#Events) + +Terms: + +* _Command_ is what frontend sends to the debugger engine +* _Answer_ is what debugger engine sends back to the frontend +* _Example_ shows simple example + +* * * + +Next: [Events](#Events), Up: [Specification](#Specification) + +### 2.1 Commands + +* [Adding Breakpoint](#Adding-Breakpoint) +* [Deleting Breakpoint](#Deleting-Breakpoint) +* [Enabling Breakpoint](#Enabling-Breakpoint) +* [Disabling Breakpoint](#Disabling-Breakpoint) +* [Condition](#Condition) +* [Catchpoint](#Catchpoint) +* [Threads](#Threads) +* [Frames](#Frames) +* [Variables](#Variables) + +* * * + +Next: [Deleting Breakpoint](#Deleting-Breakpoint), Up: [Commands](#Commands) + +#### 2.1.1 Adding Breakpoint + +Command: + + break