ruby-debug-ide 0.4.17.beta9 → 0.4.17.beta12
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/bin/rdebug-ide +27 -5
- data/lib/ruby-debug-ide.rb +16 -5
- data/lib/ruby-debug-ide/event_processor.rb +1 -1
- data/lib/ruby-debug-ide/interface.rb +1 -0
- data/lib/ruby-debug-ide/multiprocess.rb +7 -0
- data/lib/ruby-debug-ide/multiprocess/monkey.rb +45 -0
- data/lib/ruby-debug-ide/multiprocess/pre_child.rb +72 -0
- data/lib/ruby-debug-ide/multiprocess/starter.rb +10 -0
- data/lib/ruby-debug-ide/version.rb +1 -1
- data/lib/ruby-debug-ide/xml_printer.rb +1 -1
- metadata +59 -28
data/Gemfile
CHANGED
data/bin/rdebug-ide
CHANGED
@@ -25,7 +25,9 @@ options = OpenStruct.new(
|
|
25
25
|
'load_mode' => false,
|
26
26
|
'port' => 1234,
|
27
27
|
'stop' => false,
|
28
|
-
'tracing' => false
|
28
|
+
'tracing' => false,
|
29
|
+
'int_handler' => true,
|
30
|
+
'dispatcher_port' => -1
|
29
31
|
)
|
30
32
|
|
31
33
|
opts = OptionParser.new do |opts|
|
@@ -37,7 +39,10 @@ EOB
|
|
37
39
|
opts.separator ""
|
38
40
|
opts.separator "Options:"
|
39
41
|
opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host}
|
40
|
-
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
|
42
|
+
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
|
43
|
+
opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp|
|
44
|
+
options.dispatcher_port = dp
|
45
|
+
end
|
41
46
|
opts.on('--stop', 'stop when the script is loaded') {options.stop = true}
|
42
47
|
opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true}
|
43
48
|
opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true}
|
@@ -52,6 +57,7 @@ EOB
|
|
52
57
|
end
|
53
58
|
|
54
59
|
opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true}
|
60
|
+
opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false}
|
55
61
|
opts.separator ""
|
56
62
|
opts.separator "Common options:"
|
57
63
|
opts.on_tail("-v", "--version", "Show version") do
|
@@ -84,9 +90,25 @@ end
|
|
84
90
|
|
85
91
|
# save script name
|
86
92
|
Debugger::PROG_SCRIPT = ARGV.shift
|
87
|
-
|
88
|
-
|
89
|
-
|
93
|
+
|
94
|
+
if (options.dispatcher_port != -1)
|
95
|
+
ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s
|
96
|
+
if RUBY_VERSION < "1.9"
|
97
|
+
require 'ruby-debug-ide/multiprocess'
|
98
|
+
else
|
99
|
+
require_relative '../lib/ruby-debug-ide/multiprocess'
|
100
|
+
end
|
101
|
+
|
102
|
+
ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB']
|
103
|
+
old_opts = ENV['RUBYOPT']
|
104
|
+
ENV['RUBYOPT'] = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter"
|
105
|
+
ENV['RUBYOPT'] += " #{old_opts}" if old_opts
|
106
|
+
end
|
107
|
+
|
108
|
+
if options.int_handler
|
109
|
+
# install interruption handler
|
110
|
+
trap('INT') { Debugger.interrupt_last }
|
111
|
+
end
|
90
112
|
|
91
113
|
# set options
|
92
114
|
Debugger.keep_frame_binding = options.frame_bind
|
data/lib/ruby-debug-ide.rb
CHANGED
@@ -15,6 +15,7 @@ module Debugger
|
|
15
15
|
# Prints to the stderr using printf(*args) if debug logging flag (-d) is on.
|
16
16
|
def print_debug(*args)
|
17
17
|
if Debugger.cli_debug
|
18
|
+
$stderr.printf("#{Process.pid}: ")
|
18
19
|
$stderr.printf(*args)
|
19
20
|
$stderr.printf("\n")
|
20
21
|
$stderr.flush
|
@@ -76,7 +77,8 @@ module Debugger
|
|
76
77
|
class << self
|
77
78
|
|
78
79
|
attr_accessor :event_processor, :cli_debug, :xml_debug
|
79
|
-
|
80
|
+
attr_accessor :control_thread
|
81
|
+
attr_reader :interface
|
80
82
|
|
81
83
|
#
|
82
84
|
# Interrupts the current thread
|
@@ -104,7 +106,7 @@ module Debugger
|
|
104
106
|
start_control(host, port)
|
105
107
|
end
|
106
108
|
|
107
|
-
def
|
109
|
+
def prepare_debugger(options)
|
108
110
|
start_server(options.host, options.port)
|
109
111
|
|
110
112
|
raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive?
|
@@ -116,7 +118,11 @@ module Debugger
|
|
116
118
|
@mutex.synchronize do
|
117
119
|
@proceed.wait(@mutex)
|
118
120
|
end
|
119
|
-
|
121
|
+
end
|
122
|
+
|
123
|
+
def debug_program(options)
|
124
|
+
prepare_debugger(options)
|
125
|
+
|
120
126
|
abs_prog_script = File.expand_path(Debugger::PROG_SCRIPT)
|
121
127
|
bt = debug_load(abs_prog_script, options.stop, options.load_mode)
|
122
128
|
if bt && !bt.is_a?(SystemExit)
|
@@ -143,13 +149,18 @@ module Debugger
|
|
143
149
|
$stderr.printf "Fast Debugger (ruby-debug-ide #{IDE_VERSION}, ruby-debug-base #{VERSION}) listens on #{host}:#{port}\n"
|
144
150
|
server = TCPServer.new(host, port)
|
145
151
|
while (session = server.accept)
|
152
|
+
$stderr.puts "Connected from #{session.addr[2]}" if Debugger.cli_debug
|
153
|
+
dispatcher = ENV['IDE_PROCESS_DISPATCHER']
|
154
|
+
if (dispatcher)
|
155
|
+
ENV['IDE_PROCESS_DISPATCHER'] = "#{session.addr[2]}:#{dispatcher}" unless dispatcher.include?(":")
|
156
|
+
end
|
146
157
|
begin
|
147
|
-
interface = RemoteInterface.new(session)
|
158
|
+
@interface = RemoteInterface.new(session)
|
148
159
|
@event_processor = EventProcessor.new(interface)
|
149
160
|
IdeControlCommandProcessor.new(interface).process_commands
|
150
161
|
rescue StandardError, ScriptError => ex
|
151
162
|
bt = ex.backtrace
|
152
|
-
$stderr.printf "Exception in DebugThread loop: #{ex.message}\nBacktrace:\n#{bt ? bt.join("\n from: ") : "<none>"}\n"
|
163
|
+
$stderr.printf "#{Process.pid}: Exception in DebugThread loop: #{ex.message}\nBacktrace:\n#{bt ? bt.join("\n from: ") : "<none>"}\n"
|
153
164
|
exit 1
|
154
165
|
end
|
155
166
|
end
|
@@ -53,7 +53,7 @@ require 'ruby-debug-ide/xml_printer'
|
|
53
53
|
@last_breakpoint = nil
|
54
54
|
end
|
55
55
|
raise "DebuggerThread are not supposed to be traced (#{context.thread})" if context.thread.is_a?(Debugger::DebugThread)
|
56
|
-
@printer.print_debug("Stopping Thread %s", context.thread.to_s)
|
56
|
+
@printer.print_debug("Stopping Thread %s (%s)", context.thread.to_s, Process.pid.to_s)
|
57
57
|
@printer.print_debug("Threads equal: %s", Thread.current == context.thread)
|
58
58
|
IdeCommandProcessor.new(@interface).process_commands
|
59
59
|
InspectCommand.clear_references
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Debugger
|
2
|
+
module MultiProcess
|
3
|
+
def self.create_mp_fork
|
4
|
+
%Q{
|
5
|
+
alias pre_debugger_fork fork
|
6
|
+
|
7
|
+
def fork(*args)
|
8
|
+
if block_given?
|
9
|
+
return pre_debugger_fork{Debugger::MultiProcess::pre_child; yield}
|
10
|
+
end
|
11
|
+
result = pre_debugger_fork
|
12
|
+
Debugger::MultiProcess::pre_child unless result
|
13
|
+
result
|
14
|
+
end
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.create_mp_exec
|
19
|
+
%Q{
|
20
|
+
alias pre_debugger_exec exec
|
21
|
+
|
22
|
+
def exec(*args)
|
23
|
+
Debugger.interface.close
|
24
|
+
pre_debugger_exec(*args)
|
25
|
+
end
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Kernel
|
32
|
+
class << self
|
33
|
+
module_eval Debugger::MultiProcess.create_mp_fork
|
34
|
+
module_eval Debugger::MultiProcess.create_mp_exec
|
35
|
+
end
|
36
|
+
module_eval Debugger::MultiProcess.create_mp_fork
|
37
|
+
module_eval Debugger::MultiProcess.create_mp_exec
|
38
|
+
end
|
39
|
+
|
40
|
+
module Process
|
41
|
+
class << self
|
42
|
+
module_eval Debugger::MultiProcess.create_mp_fork
|
43
|
+
module_eval Debugger::MultiProcess.create_mp_exec
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Debugger
|
2
|
+
module MultiProcess
|
3
|
+
class << self
|
4
|
+
def pre_child
|
5
|
+
|
6
|
+
require "socket"
|
7
|
+
require "ostruct"
|
8
|
+
|
9
|
+
host = '127.0.0.1'
|
10
|
+
port = find_free_port(host)
|
11
|
+
|
12
|
+
options = OpenStruct.new(
|
13
|
+
'frame_bind' => false,
|
14
|
+
'host' => host,
|
15
|
+
'load_mode' => false,
|
16
|
+
'port' => port,
|
17
|
+
'stop' => false,
|
18
|
+
'tracing' => false,
|
19
|
+
'int_handler' => true
|
20
|
+
)
|
21
|
+
|
22
|
+
acceptor_host, acceptor_port = ENV['IDE_PROCESS_DISPATCHER'].split(":")
|
23
|
+
acceptor_host, acceptor_port = '127.0.0.1', acceptor_host unless acceptor_port
|
24
|
+
|
25
|
+
connected = false
|
26
|
+
3.times do |i|
|
27
|
+
begin
|
28
|
+
s = TCPSocket.open(acceptor_host, acceptor_port)
|
29
|
+
s.print(port)
|
30
|
+
s.close
|
31
|
+
connected = true
|
32
|
+
start_debugger(options)
|
33
|
+
return
|
34
|
+
rescue => bt
|
35
|
+
$stderr.puts "#{Process.pid}: connection failed(#{i+1})"
|
36
|
+
$stderr.puts "Exception: #{bt}"
|
37
|
+
$stderr.puts bt.backtrace.map { |l| "\t#{l}" }.join("\n")
|
38
|
+
sleep 0.3
|
39
|
+
end unless connected
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def start_debugger(options)
|
44
|
+
if Debugger.started?
|
45
|
+
#we're in forked child, only need to restart control thread
|
46
|
+
Debugger.breakpoints.clear
|
47
|
+
Debugger.control_thread = nil
|
48
|
+
Debugger.start_control(options.host, options.port)
|
49
|
+
end
|
50
|
+
|
51
|
+
if options.int_handler
|
52
|
+
# install interruption handler
|
53
|
+
trap('INT') { Debugger.interrupt_last }
|
54
|
+
end
|
55
|
+
|
56
|
+
# set options
|
57
|
+
Debugger.keep_frame_binding = options.frame_bind
|
58
|
+
Debugger.tracing = options.tracing
|
59
|
+
|
60
|
+
Debugger.prepare_debugger(options)
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def find_free_port(host)
|
65
|
+
server = TCPServer.open(host, 0)
|
66
|
+
port = server.addr[1]
|
67
|
+
server.close
|
68
|
+
port
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
if ENV['IDE_PROCESS_DISPATCHER']
|
2
|
+
require 'rubygems'
|
3
|
+
ENV['DEBUGGER_STORED_RUBYLIB'].split(File::PATH_SEPARATOR).each do |path|
|
4
|
+
next unless path =~ /ruby-debug-ide|ruby-debug-base|linecache/
|
5
|
+
$LOAD_PATH << path
|
6
|
+
end
|
7
|
+
require 'ruby-debug-ide'
|
8
|
+
require 'ruby-debug-ide/multiprocess'
|
9
|
+
Debugger::MultiProcess::pre_child
|
10
|
+
end
|
@@ -92,7 +92,7 @@ module Debugger
|
|
92
92
|
|
93
93
|
def print_context(context)
|
94
94
|
current = 'current="yes"' if context.thread == Thread.current
|
95
|
-
print "<thread id=\"%s\" status=\"%s\" #{current}/>", context.thnum, context.thread.status
|
95
|
+
print "<thread id=\"%s\" status=\"%s\" pid=\"%s\" #{current}/>", context.thnum, context.thread.status, Process.pid
|
96
96
|
end
|
97
97
|
|
98
98
|
def print_variables(vars, kind)
|
metadata
CHANGED
@@ -1,38 +1,51 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-debug-ide
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 62196339
|
5
5
|
prerelease: 7
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 17
|
10
|
+
- beta
|
11
|
+
- 12
|
12
|
+
version: 0.4.17.beta12
|
6
13
|
platform: ruby
|
7
|
-
authors:
|
14
|
+
authors:
|
8
15
|
- Markus Barchfeld, Martin Krauskopf, Mark Moseley, JetBrains RubyMine Team
|
9
16
|
autorequire:
|
10
17
|
bindir: bin
|
11
18
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
19
|
+
|
20
|
+
date: 2012-06-07 00:00:00 Z
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
15
23
|
name: rake
|
16
|
-
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
26
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 61
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
- 8
|
34
|
+
- 1
|
21
35
|
version: 0.8.1
|
22
36
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
and RubyMine.
|
37
|
+
version_requirements: *id001
|
38
|
+
description: |
|
39
|
+
An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine.
|
27
40
|
|
28
|
-
'
|
29
41
|
email: rubymine-feedback@jetbrains.com
|
30
|
-
executables:
|
42
|
+
executables:
|
31
43
|
- rdebug-ide
|
32
|
-
extensions:
|
44
|
+
extensions:
|
33
45
|
- ext/mkrf_conf.rb
|
34
46
|
extra_rdoc_files: []
|
35
|
-
|
47
|
+
|
48
|
+
files:
|
36
49
|
- CHANGES
|
37
50
|
- ChangeLog
|
38
51
|
- ChangeLog.archive
|
@@ -62,31 +75,49 @@ files:
|
|
62
75
|
- lib/ruby-debug-ide/helper.rb
|
63
76
|
- lib/ruby-debug-ide/ide_processor.rb
|
64
77
|
- lib/ruby-debug-ide/interface.rb
|
78
|
+
- lib/ruby-debug-ide/multiprocess/monkey.rb
|
79
|
+
- lib/ruby-debug-ide/multiprocess/pre_child.rb
|
80
|
+
- lib/ruby-debug-ide/multiprocess/starter.rb
|
81
|
+
- lib/ruby-debug-ide/multiprocess.rb
|
65
82
|
- lib/ruby-debug-ide/version.rb
|
66
83
|
- lib/ruby-debug-ide/xml_printer.rb
|
67
84
|
- lib/ruby-debug-ide.rb
|
68
85
|
homepage: https://github.com/JetBrains/ruby-debug-ide
|
69
86
|
licenses: []
|
87
|
+
|
70
88
|
post_install_message:
|
71
89
|
rdoc_options: []
|
72
|
-
|
90
|
+
|
91
|
+
require_paths:
|
73
92
|
- lib
|
74
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
94
|
none: false
|
76
|
-
requirements:
|
77
|
-
- -
|
78
|
-
- !ruby/object:Gem::Version
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 51
|
99
|
+
segments:
|
100
|
+
- 1
|
101
|
+
- 8
|
102
|
+
- 2
|
79
103
|
version: 1.8.2
|
80
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
105
|
none: false
|
82
|
-
requirements:
|
83
|
-
- -
|
84
|
-
- !ruby/object:Gem::Version
|
106
|
+
requirements:
|
107
|
+
- - ">"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 25
|
110
|
+
segments:
|
111
|
+
- 1
|
112
|
+
- 3
|
113
|
+
- 1
|
85
114
|
version: 1.3.1
|
86
115
|
requirements: []
|
116
|
+
|
87
117
|
rubyforge_project: debug-commons
|
88
118
|
rubygems_version: 1.8.6
|
89
119
|
signing_key:
|
90
120
|
specification_version: 3
|
91
121
|
summary: IDE interface for ruby-debug.
|
92
122
|
test_files: []
|
123
|
+
|