ruby-debug-ide-docker 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +75 -0
  3. data/ChangeLog.archive +1073 -0
  4. data/ChangeLog.md +594 -0
  5. data/Gemfile +28 -0
  6. data/MIT-LICENSE +24 -0
  7. data/Rakefile +42 -0
  8. data/bin/gdb_wrapper +96 -0
  9. data/bin/rdebug-ide +183 -0
  10. data/ext/mkrf_conf.rb +48 -0
  11. data/lib/ruby-debug-ide.rb +173 -0
  12. data/lib/ruby-debug-ide/attach/debugger_loader.rb +20 -0
  13. data/lib/ruby-debug-ide/attach/gdb.rb +73 -0
  14. data/lib/ruby-debug-ide/attach/lldb.rb +71 -0
  15. data/lib/ruby-debug-ide/attach/native_debugger.rb +133 -0
  16. data/lib/ruby-debug-ide/attach/process_thread.rb +54 -0
  17. data/lib/ruby-debug-ide/attach/util.rb +115 -0
  18. data/lib/ruby-debug-ide/command.rb +177 -0
  19. data/lib/ruby-debug-ide/commands/breakpoints.rb +128 -0
  20. data/lib/ruby-debug-ide/commands/catchpoint.rb +64 -0
  21. data/lib/ruby-debug-ide/commands/condition.rb +51 -0
  22. data/lib/ruby-debug-ide/commands/control.rb +158 -0
  23. data/lib/ruby-debug-ide/commands/enable.rb +203 -0
  24. data/lib/ruby-debug-ide/commands/eval.rb +64 -0
  25. data/lib/ruby-debug-ide/commands/expression_info.rb +71 -0
  26. data/lib/ruby-debug-ide/commands/file_filtering.rb +107 -0
  27. data/lib/ruby-debug-ide/commands/frame.rb +155 -0
  28. data/lib/ruby-debug-ide/commands/inspect.rb +25 -0
  29. data/lib/ruby-debug-ide/commands/jump.rb +73 -0
  30. data/lib/ruby-debug-ide/commands/load.rb +18 -0
  31. data/lib/ruby-debug-ide/commands/pause.rb +33 -0
  32. data/lib/ruby-debug-ide/commands/set_type.rb +47 -0
  33. data/lib/ruby-debug-ide/commands/stepping.rb +108 -0
  34. data/lib/ruby-debug-ide/commands/threads.rb +178 -0
  35. data/lib/ruby-debug-ide/commands/variables.rb +154 -0
  36. data/lib/ruby-debug-ide/event_processor.rb +71 -0
  37. data/lib/ruby-debug-ide/greeter.rb +40 -0
  38. data/lib/ruby-debug-ide/helper.rb +33 -0
  39. data/lib/ruby-debug-ide/ide_processor.rb +155 -0
  40. data/lib/ruby-debug-ide/interface.rb +45 -0
  41. data/lib/ruby-debug-ide/multiprocess.rb +23 -0
  42. data/lib/ruby-debug-ide/multiprocess/monkey.rb +47 -0
  43. data/lib/ruby-debug-ide/multiprocess/pre_child.rb +67 -0
  44. data/lib/ruby-debug-ide/multiprocess/starter.rb +11 -0
  45. data/lib/ruby-debug-ide/multiprocess/unmonkey.rb +31 -0
  46. data/lib/ruby-debug-ide/version.rb +3 -0
  47. data/lib/ruby-debug-ide/xml_printer.rb +545 -0
  48. data/ruby-debug-ide-docker.gemspec +51 -0
  49. metadata +110 -0
data/Gemfile ADDED
@@ -0,0 +1,28 @@
1
+ source "http://rubygems.org"
2
+
3
+ # @param [Array<String>] versions compatible ruby versions
4
+ # @return [Array<String>] an array with mri platforms of given versions
5
+ def mries(*versions)
6
+ versions.flat_map do |v|
7
+ %w(ruby mingw x64_mingw)
8
+ .map { |platform| "#{platform}_#{v}".to_sym unless platform == "x64_mingw" && v < "2.0" }
9
+ .delete_if &:nil?
10
+ end
11
+ end
12
+
13
+ gem "ruby-debug-base", :platforms => [:jruby, *mries('18')]
14
+ gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19')
15
+ if RUBY_VERSION && RUBY_VERSION >= "2.0"
16
+ gem "debase", "~> 0.2.2", :platforms => mries('20', '21', '22', '23', '24', '25')
17
+ end
18
+
19
+ gemspec
20
+
21
+ group :development do
22
+ gem "bundler"
23
+ end
24
+
25
+ group :test do
26
+ gem "test-unit"
27
+ end
28
+
@@ -0,0 +1,24 @@
1
+ The file lib/classic-debug.rb is based on the debug.rb file from Ruby
2
+ project.
3
+
4
+ Copyright (c) 2007-2008, debug-commons team
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
@@ -0,0 +1,42 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ desc 'Default: run unit tests.'
5
+ task :default => [:test]
6
+
7
+ # Unit tests
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test"
10
+ t.libs << "test-base"
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ t.warning = false
14
+ end
15
+
16
+ desc "Create a ChangeLog"
17
+ # simple rake task to output a changelog between two commits, tags ...
18
+ # output is formatted simply, commits are grouped under each author name
19
+ desc "generate changelog with nice clean output"
20
+ task :changelog, :since_c, :until_c do |t,args|
21
+ since_c = args[:since_c] || `git tag | head -1`.chomp
22
+ until_c = args[:until_c]
23
+ cmd=`git log --pretty='format:%ci::%an <%ae>::%s::%H' #{since_c}..#{until_c}`
24
+
25
+ entries = Hash.new
26
+ changelog_content = String.new
27
+
28
+ cmd.split("\n").each do |entry|
29
+ date, author, subject, hash = entry.chomp.split("::")
30
+ entries[author] = Array.new unless entries[author]
31
+ day = date.split(" ").first
32
+ entries[author] << "#{subject} (#{hash})" unless subject =~ /Merge/
33
+ end
34
+
35
+ # generate clean output
36
+ entries.keys.each do |author|
37
+ changelog_content += author + "\n"
38
+ entries[author].reverse.each { |entry| changelog_content += " * #{entry}\n" }
39
+ end
40
+
41
+ puts changelog_content
42
+ end
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'thread'
5
+ require 'ostruct'
6
+
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ options = OpenStruct.new(
11
+ 'pid' => nil,
12
+ 'sdk_path' => nil,
13
+ 'uid' => nil,
14
+ 'gems_to_include' => []
15
+ )
16
+
17
+ module DebugPrinter
18
+
19
+ class << self
20
+ attr_accessor :cli_debug
21
+
22
+ def print_debug(msg)
23
+ if DebugPrinter.cli_debug
24
+ $stderr.puts msg
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ DebugPrinter.cli_debug = ARGV.include? '--debug'
32
+
33
+ opts = OptionParser.new do |opts|
34
+ # TODO need some banner
35
+ opts.banner = <<EOB
36
+ Some useful banner.
37
+ EOB
38
+
39
+ opts.on('--pid PID', 'pid of process you want to attach to for debugging') do |pid|
40
+ options.pid = pid
41
+ end
42
+
43
+ opts.on('--ruby-path RUBY_PATH', 'path to ruby interpreter') do |ruby_path|
44
+ options.ruby_path = ruby_path
45
+ end
46
+
47
+ opts.on('--uid UID', 'uid which this process should set after executing gdb attach') do |uid|
48
+ options.uid = uid
49
+ end
50
+
51
+ opts.on('--include-gem GEM_LIB_PATH', 'lib of gem to include') do |gem_lib_path|
52
+ options.gems_to_include << gem_lib_path
53
+ end
54
+ end
55
+
56
+ opts.parse! ARGV
57
+
58
+ unless options.pid
59
+ $stderr.puts 'You should specify PID of process you want to attach to'
60
+ exit 1
61
+ end
62
+
63
+ unless options.ruby_path
64
+ $stderr.puts 'You should specify path to the ruby interpreter'
65
+ exit 1
66
+ end
67
+
68
+ argv = '["' + ARGV * '", "' + '"]'
69
+ child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]'
70
+ debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader'
71
+
72
+ options.gems_to_include.each do |gem_path|
73
+ $LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path)
74
+ end
75
+
76
+ require 'ruby-debug-ide/greeter'
77
+ Debugger::print_greeting_msg($stdout, nil, nil)
78
+
79
+ require 'ruby-debug-ide/attach/util'
80
+ require 'ruby-debug-ide/attach/native_debugger'
81
+ require 'ruby-debug-ide/attach/process_thread'
82
+
83
+
84
+ child_pids = get_child_pids(options.pid.to_s)
85
+ attach_threads = Array.new
86
+ attach_threads << attach_and_return_thread(options, options.pid, debugger_loader_path, argv)
87
+
88
+ attach_threads << child_pids.map {|pid| attach_and_return_thread(options, pid, debugger_loader_path, child_argv)}
89
+
90
+
91
+ attach_threads.each {|thread| thread.join}
92
+ if options.uid
93
+ DebugPrinter.print_debug("changing current uid from #{Process.uid} to #{options.uid}")
94
+ Process::Sys.setuid(options.uid.to_i)
95
+ end
96
+ sleep
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'optparse'
4
+ require "ostruct"
5
+ if RUBY_VERSION < "1.9"
6
+ require 'ruby-debug-ide'
7
+ else
8
+ require_relative '../lib/ruby-debug-ide'
9
+ end
10
+
11
+ $stdout.sync=true
12
+
13
+ options = OpenStruct.new(
14
+ 'frame_bind' => false,
15
+ 'host' => nil,
16
+ 'load_mode' => false,
17
+ 'port' => 1234,
18
+ 'stop' => false,
19
+ 'tracing' => false,
20
+ 'int_handler' => true,
21
+ 'dispatcher_port' => -1,
22
+ 'evaluation_timeout' => 10,
23
+ 'trace_to_s' => false,
24
+ 'debugger_memory_limit' => 10,
25
+ 'inspect_time_limit' => 100,
26
+ 'rm_protocol_extensions' => false,
27
+ 'catchpoint_deleted_event' => false,
28
+ 'value_as_nested_element' => false,
29
+ 'attach_mode' => false,
30
+ 'cli_debug' => false
31
+ )
32
+
33
+ opts = OptionParser.new do |opts|
34
+ opts.banner = <<EOB
35
+ Using ruby-debug-base #{Debugger::VERSION}
36
+ Usage: rdebug-ide is supposed to be called from RDT, NetBeans, RubyMine, or
37
+ the IntelliJ IDEA Ruby plugin. The command line interface to
38
+ ruby-debug is rdebug.
39
+ EOB
40
+ opts.separator ""
41
+ opts.separator "Options:"
42
+
43
+ opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host}
44
+ opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
45
+ opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp|
46
+ options.dispatcher_port = dp
47
+ end
48
+ opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout|
49
+ options.evaluation_timeout = timeout
50
+ end
51
+ opts.on("--evaluation-control", "trace to_s evaluation") {options.trace_to_s = true}
52
+
53
+ opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit|
54
+ if defined?(JRUBY_VERSION) || RUBY_VERSION < '2.0'
55
+ $stderr.puts "Evaluation memory limit is ineffective in JRuby and MRI < 2.0"
56
+ limit = 0
57
+ end
58
+ options.debugger_memory_limit = limit
59
+ options.trace_to_s ||= limit > 0
60
+ end
61
+
62
+ opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit|
63
+ options.inspect_time_limit = limit
64
+ options.trace_to_s ||= limit > 0
65
+ end
66
+
67
+ opts.on('--stop', 'stop when the script is loaded') {options.stop = true}
68
+ opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true}
69
+ opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true}
70
+ opts.on("-d", "--debug", "Debug self - prints information for debugging ruby-debug itself") do
71
+ Debugger.cli_debug = true
72
+ options.cli_debug = true
73
+ end
74
+ opts.on("--xml-debug", "Debug self - sends information <message>s for debugging ruby-debug itself") do
75
+ Debugger.xml_debug = true
76
+ end
77
+ opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path|
78
+ $LOAD_PATH.unshift(path)
79
+ end
80
+ opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do
81
+ options.attach_mode = true
82
+ end
83
+ opts.on("--ignore-port", "Generate another port") do
84
+ options.ignore_port = true
85
+ end
86
+ opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true}
87
+ opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false}
88
+ opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do
89
+ options.rm_protocol_extensions = true
90
+ end
91
+ opts.on("--catchpoint-deleted-event", "Enable chatchpointDeleted event") do
92
+ options.catchpoint_deleted_event = true
93
+ end
94
+ opts.on("--value-as-nested-element", "Allow to pass variable's value as nested element instead of attribute") do
95
+ options.value_as_nested_element = true
96
+ end
97
+ opts.separator ""
98
+ opts.separator "Common options:"
99
+ opts.on_tail("-v", "--version", "Show version") do
100
+ puts "Using ruby-debug-base #{Debugger::VERSION}"
101
+ exit
102
+ end
103
+ end
104
+
105
+ begin
106
+ Debugger::ARGV = ARGV.clone
107
+ rdebug_path = File.expand_path($0)
108
+ if RUBY_PLATFORM =~ /mswin/
109
+ rdebug_path += ".cmd" unless rdebug_path =~ /\.cmd$/i
110
+ end
111
+ Debugger::RDEBUG_SCRIPT = rdebug_path
112
+ opts.parse! ARGV
113
+ rescue StandardError => e
114
+ puts opts
115
+ puts
116
+ puts e.message
117
+ exit(1)
118
+ end
119
+
120
+ if ARGV.empty? && !options.attach_mode
121
+ puts opts
122
+ puts
123
+ puts "Must specify a script to run"
124
+ exit(1)
125
+ end
126
+
127
+ # save script name
128
+ if !options.attach_mode
129
+ Debugger::PROG_SCRIPT = ARGV.shift
130
+ else
131
+ Debugger::PROG_SCRIPT = $0
132
+ end
133
+
134
+ if options.dispatcher_port != -1
135
+ ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s
136
+ if RUBY_VERSION < "1.9"
137
+ lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
138
+ $: << lib_path unless $:.include? lib_path
139
+ require 'ruby-debug-ide/multiprocess'
140
+ else
141
+ require_relative '../lib/ruby-debug-ide/multiprocess'
142
+ end
143
+ Debugger::MultiProcess.do_monkey
144
+
145
+ ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB']
146
+ old_opts = ENV['RUBYOPT'] || ''
147
+ starter = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter"
148
+ unless old_opts.include? starter
149
+ ENV['RUBYOPT'] = starter
150
+ ENV['RUBYOPT'] += " #{old_opts}" if old_opts != ''
151
+ end
152
+ ENV['DEBUGGER_CLI_DEBUG'] = Debugger.cli_debug.to_s
153
+ end
154
+
155
+ if options.int_handler
156
+ # install interruption handler
157
+ trap('INT') { Debugger.interrupt_last }
158
+ end
159
+
160
+ # set options
161
+ Debugger.keep_frame_binding = options.frame_bind
162
+ Debugger.tracing = options.tracing
163
+ Debugger.evaluation_timeout = options.evaluation_timeout
164
+ Debugger.trace_to_s = options.trace_to_s && (options.debugger_memory_limit > 0 || options.inspect_time_limit > 0)
165
+ Debugger.debugger_memory_limit = options.debugger_memory_limit
166
+ Debugger.inspect_time_limit = options.inspect_time_limit
167
+ Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions
168
+ Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions
169
+
170
+ if options.attach_mode
171
+ if Debugger::FRONT_END == "debase"
172
+ Debugger.init_variables
173
+ end
174
+
175
+ Debugger::MultiProcess::pre_child(options)
176
+
177
+ if Debugger::FRONT_END == "debase"
178
+ Debugger.setup_tracepoints
179
+ Debugger.prepare_context
180
+ end
181
+ else
182
+ Debugger.debug_program(options)
183
+ end
@@ -0,0 +1,48 @@
1
+ jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE)
2
+ rbx = defined?(RUBY_ENGINE) && 'rbx' == RUBY_ENGINE
3
+
4
+ def already_installed(dep)
5
+ !Gem::DependencyInstaller.new(:domain => :local).find_gems_with_sources(dep).empty? ||
6
+ !Gem::DependencyInstaller.new(:domain => :local,:prerelease => true).find_gems_with_sources(dep).empty?
7
+ end
8
+
9
+ unless jruby || rbx
10
+ require 'rubygems'
11
+ require 'rubygems/command.rb'
12
+ require 'rubygems/dependency.rb'
13
+ require 'rubygems/dependency_installer.rb'
14
+
15
+ begin
16
+ Gem::Command.build_args = ARGV
17
+ rescue NoMethodError
18
+ end
19
+
20
+ if RUBY_VERSION < "1.9"
21
+ dep = Gem::Dependency.new("ruby-debug-base", '>=0.10.4')
22
+ elsif RUBY_VERSION < '2.0'
23
+ dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.30.pre15')
24
+ else
25
+ dep = Gem::Dependency.new("debase", '> 0')
26
+ end
27
+
28
+ begin
29
+ puts "Installing base gem"
30
+ inst = Gem::DependencyInstaller.new :prerelease => dep.prerelease?
31
+ inst.install dep
32
+ rescue
33
+ begin
34
+ inst = Gem::DependencyInstaller.new(:prerelease => true)
35
+ inst.install dep
36
+ rescue Exception => e
37
+ puts e
38
+ puts e.backtrace.join "\n "
39
+ exit(1)
40
+ end
41
+ end unless dep.nil? || already_installed(dep)
42
+ end
43
+
44
+ # create dummy rakefile to indicate success
45
+ f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w")
46
+ f.write("task :default\n")
47
+ f.close
48
+
@@ -0,0 +1,173 @@
1
+ require 'pp'
2
+ require 'stringio'
3
+ require "socket"
4
+ require 'thread'
5
+ if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION)
6
+ require 'ruby-debug-base'
7
+ Debugger::FRONT_END = "ruby-debug-base"
8
+ else
9
+ require 'debase'
10
+ Debugger::FRONT_END = "debase"
11
+ end
12
+
13
+ require 'ruby-debug-ide/greeter'
14
+ require 'ruby-debug-ide/xml_printer'
15
+ require 'ruby-debug-ide/ide_processor'
16
+ require 'ruby-debug-ide/event_processor'
17
+
18
+ module Debugger
19
+
20
+ class << self
21
+ # Prints to the stderr using printf(*args) if debug logging flag (-d) is on.
22
+ def print_debug(*args)
23
+ if Debugger.cli_debug
24
+ $stderr.printf("#{Process.pid}: ")
25
+ $stderr.printf(*args)
26
+ $stderr.printf("\n")
27
+ $stderr.flush
28
+ end
29
+ end
30
+
31
+ def cleanup_backtrace(backtrace)
32
+ cleared = []
33
+ return cleared unless backtrace
34
+ backtrace.each do |line|
35
+ if line.index(File.expand_path(File.dirname(__FILE__) + "/..")) == 0
36
+ next
37
+ end
38
+ if line.index("-e:1") == 0
39
+ break
40
+ end
41
+ cleared << line
42
+ end
43
+ cleared
44
+ end
45
+
46
+ attr_accessor :attached
47
+ attr_accessor :cli_debug, :xml_debug, :evaluation_timeout
48
+ attr_accessor :trace_to_s, :debugger_memory_limit, :inspect_time_limit
49
+ attr_accessor :control_thread
50
+ attr_reader :interface
51
+ # protocol extensions
52
+ attr_accessor :catchpoint_deleted_event, :value_as_nested_element
53
+
54
+
55
+ #
56
+ # Interrupts the last debugged thread
57
+ #
58
+ def interrupt_last
59
+ skip do
60
+ if context = last_context
61
+ return nil unless context.thread.alive?
62
+ context.interrupt
63
+ end
64
+ context
65
+ end
66
+ end
67
+
68
+ def start_server(host = nil, port = 1234, notify_dispatcher = false)
69
+ return if started?
70
+ start
71
+ start_control(host, port, notify_dispatcher)
72
+ end
73
+
74
+ def prepare_debugger(options)
75
+ @mutex = Mutex.new
76
+ @proceed = ConditionVariable.new
77
+
78
+ start_server(options.host, options.port, options.notify_dispatcher)
79
+
80
+ raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive?
81
+
82
+ # wait for 'start' command
83
+ @mutex.synchronize do
84
+ @proceed.wait(@mutex)
85
+ end
86
+ end
87
+
88
+ def debug_program(options)
89
+ prepare_debugger(options)
90
+
91
+ abs_prog_script = File.expand_path(Debugger::PROG_SCRIPT)
92
+ bt = debug_load(abs_prog_script, options.stop, options.load_mode)
93
+ if bt && !bt.is_a?(SystemExit)
94
+ $stderr.print "Uncaught exception: #{bt}\n"
95
+ $stderr.print Debugger.cleanup_backtrace(bt.backtrace).map{|l| "\t#{l}"}.join("\n"), "\n"
96
+ end
97
+ end
98
+
99
+ def run_prog_script
100
+ return unless @mutex
101
+ @mutex.synchronize do
102
+ @proceed.signal
103
+ end
104
+ end
105
+
106
+ def start_control(host, port, notify_dispatcher)
107
+ raise "Debugger is not started" unless started?
108
+ return if @control_thread
109
+ @control_thread = DebugThread.new do
110
+ begin
111
+ # 127.0.0.1 seemingly works with all systems and with IPv6 as well.
112
+ # "localhost" and nil have problems on some systems.
113
+ host ||= '127.0.0.1'
114
+ server = TCPServer.new(host, port)
115
+ print_greeting_msg($stderr, host, port) if defined? IDE_VERSION
116
+ notify_dispatcher(port) if notify_dispatcher
117
+ while (session = server.accept)
118
+ $stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug
119
+ dispatcher = ENV['IDE_PROCESS_DISPATCHER']
120
+ if dispatcher
121
+ ENV['IDE_PROCESS_DISPATCHER'] = "#{session.peeraddr[2]}:#{dispatcher}" unless dispatcher.include?(":")
122
+ ENV['DEBUGGER_HOST'] = host
123
+ end
124
+ begin
125
+ @interface = RemoteInterface.new(session)
126
+ self.handler = EventProcessor.new(interface)
127
+ IdeControlCommandProcessor.new(interface).process_commands
128
+ rescue StandardError, ScriptError => ex
129
+ bt = ex.backtrace
130
+ $stderr.printf "#{Process.pid}: Exception in DebugThread loop: #{ex.message}(#{ex.class})\nBacktrace:\n#{bt ? bt.join("\n from: ") : "<none>"}\n"
131
+ exit 1
132
+ end
133
+ end
134
+ rescue
135
+ bt = $!.backtrace
136
+ $stderr.printf "Fatal exception in DebugThread loop: #{$!.message}\nBacktrace:\n#{bt ? bt.join("\n from: ") : "<none>"}\n"
137
+ exit 2
138
+ end
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+
145
+ def notify_dispatcher(port)
146
+ return unless ENV['IDE_PROCESS_DISPATCHER']
147
+ acceptor_host, acceptor_port = ENV['IDE_PROCESS_DISPATCHER'].split(":")
148
+ acceptor_host, acceptor_port = '127.0.0.1', acceptor_host unless acceptor_port
149
+ connected = false
150
+
151
+ 3.times do |i|
152
+ begin
153
+ s = TCPSocket.open(acceptor_host, acceptor_port)
154
+ s.print(port)
155
+ s.close
156
+ connected = true
157
+ print_debug "Ide process dispatcher notified about sub-debugger which listens on #{port}\n"
158
+ return
159
+ rescue => bt
160
+ $stderr.puts "#{Process.pid}: connection failed(#{i+1})"
161
+ $stderr.puts "Exception: #{bt}"
162
+ $stderr.puts bt.backtrace.map { |l| "\t#{l}" }.join("\n")
163
+ sleep 0.3
164
+ end unless connected
165
+ end
166
+ end
167
+
168
+ end
169
+
170
+ class Exception # :nodoc:
171
+ attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
172
+ end
173
+ end