ruby-debug-ide 0.6.1.beta4 → 0.6.1.beta6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 90ec6589dc3043b457fe0c148595388e8052df55
4
- data.tar.gz: b60add310e51a12ed117d28b2710a816aab51575
3
+ metadata.gz: 565c9fc5c3cf0ae3477f3b944fbe90f956420302
4
+ data.tar.gz: 8ff67628c2d6b887e8651013f6744157bc65254a
5
5
  SHA512:
6
- metadata.gz: 19c91299d491b609b74cd72e3ea4d909d5f09322bd015fa3c3451aedb019e3d7e0321c3de08cc283019e408d4612ba3cec1326f0b52890f8e1fe0aa6f520e2db
7
- data.tar.gz: b33c0c1e0ac56f69330832dfbc1631dc8dff03c886d33be8127f9352620225c7245cc9af110bfb72997294ae99efb2addac507519f4ddf01bd7810b3b9b93312
6
+ metadata.gz: fbe3852ec8b2cbf4f221912c3e679d2610198af3316b15810ef963e6cab4115d0ef716cebeeb035ed26779d2347c58637ecf55815993fdb5c5bb9d8870bbbe74
7
+ data.tar.gz: 7ebf7eb3bc7e06c95661abf449777f513a25f510de3a3ad2d952edf54b64baa70aaca9b700e984129c58102d4755c5692c46829806c606f4b59d81f452adbb16
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
+ require 'thread'
4
5
  require 'ostruct'
5
6
 
6
7
  $stdout.sync = true
@@ -65,6 +66,7 @@ unless options.ruby_path
65
66
  end
66
67
 
67
68
  argv = '["' + ARGV * '", "' + '"]'
69
+ child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]'
68
70
  debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader'
69
71
 
70
72
  options.gems_to_include.each do |gem_path|
@@ -78,51 +80,17 @@ require 'ruby-debug-ide/attach/util'
78
80
  require 'ruby-debug-ide/attach/native_debugger'
79
81
  require 'ruby-debug-ide/attach/process_thread'
80
82
 
81
- debugger = choose_debugger(options.ruby_path, options.pid, options.gems_to_include, debugger_loader_path, argv)
82
83
 
83
- trap('INT') do
84
- unless debugger.exited?
85
- $stderr.puts "backtraces for threads:\n\n"
86
- process_threads = debugger.process_threads
87
- if process_threads
88
- process_threads.each do |thread|
89
- $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n"
90
- end
91
- end
92
- debugger.exit
93
- end
94
- exit!
95
- end
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)
96
87
 
97
- debugger.attach_to_process
98
- debugger.set_flags
88
+ attach_threads << child_pids.map {|pid| attach_and_return_thread(options, pid, debugger_loader_path, child_argv)}
99
89
 
90
+
91
+ attach_threads.each {|thread| thread.join}
100
92
  if options.uid
101
93
  DebugPrinter.print_debug("changing current uid from #{Process.uid} to #{options.uid}")
102
94
  Process::Sys.setuid(options.uid.to_i)
103
95
  end
104
-
105
- if debugger.check_already_under_debug
106
- $stderr.puts "Process #{debugger.pid} is already under debug"
107
- debugger.exit
108
- exit!
109
- end
110
-
111
- should_check_threads_state = true
112
-
113
- while should_check_threads_state
114
- should_check_threads_state = false
115
- debugger.update_threads.each do |thread|
116
- thread.switch
117
- while thread.need_finish_frame
118
- should_check_threads_state = true
119
- thread.finish
120
- end
121
- end
122
- end
123
-
124
- debugger.wait_line_event
125
- debugger.load_debugger
126
- debugger.exit
127
-
128
96
  sleep
@@ -36,8 +36,19 @@ Usage: rdebug-ide is supposed to be called from RDT, NetBeans, RubyMine, or
36
36
  EOB
37
37
  opts.separator ""
38
38
  opts.separator "Options:"
39
+
40
+ ENV['DEBUGGER_MEMORY_LIMIT'] = '10'
41
+ opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit|
42
+ ENV['DEBUGGER_MEMORY_LIMIT'] = limit
43
+ end
44
+
45
+ ENV['INSPECT_TIME_LIMIT'] = '100'
46
+ opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit|
47
+ ENV['INSPECT_TIME_LIMIT'] = limit
48
+ end
49
+
39
50
  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}
51
+ opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
41
52
  opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp|
42
53
  options.dispatcher_port = dp
43
54
  end
@@ -60,6 +71,9 @@ EOB
60
71
  opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do
61
72
  options.attach_mode = true
62
73
  end
74
+ opts.on("--ignore-port", "Generate another port") do
75
+ options.ignore_port = true
76
+ end
63
77
  opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true}
64
78
  opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false}
65
79
  opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do
@@ -1,5 +1,76 @@
1
1
  require 'ruby-debug-ide/attach/lldb'
2
2
  require 'ruby-debug-ide/attach/gdb'
3
+ require 'socket'
4
+
5
+ def attach_and_return_thread(options, pid, debugger_loader_path, argv)
6
+ Thread.new(argv) do |argv|
7
+
8
+ debugger = choose_debugger(options.ruby_path, pid, options.gems_to_include, debugger_loader_path, argv)
9
+
10
+ trap('INT') do
11
+ unless debugger.exited?
12
+ $stderr.puts "backtraces for threads:\n\n"
13
+ process_threads = debugger.process_threads
14
+ if process_threads
15
+ process_threads.each do |thread|
16
+ $stderr.puts "#{thread.thread_info}\n#{thread.last_bt}\n\n"
17
+ end
18
+ end
19
+ debugger.exit
20
+ end
21
+ exit!
22
+ end
23
+
24
+ debugger.attach_to_process
25
+ debugger.set_flags
26
+
27
+ if debugger.check_already_under_debug
28
+ $stderr.puts "Process #{debugger.pid} is already under debug"
29
+ debugger.exit
30
+ exit!
31
+ end
32
+
33
+ should_check_threads_state = true
34
+
35
+ while should_check_threads_state
36
+ should_check_threads_state = false
37
+ debugger.update_threads.each do |thread|
38
+ thread.switch
39
+ while thread.need_finish_frame
40
+ should_check_threads_state = true
41
+ thread.finish
42
+ end
43
+ end
44
+ end
45
+
46
+ debugger.wait_line_event
47
+ debugger.load_debugger
48
+ debugger.exit
49
+ end
50
+ end
51
+
52
+ def get_child_pids(pid)
53
+ return [] unless command_exists 'pgrep'
54
+
55
+ pids = Array.new
56
+
57
+ q = Queue.new
58
+ q.push(pid)
59
+
60
+ while (!q.empty?) do
61
+ pid = q.pop
62
+
63
+ pipe = IO.popen("pgrep -P #{pid}")
64
+
65
+ pipe.readlines.each do |child|
66
+ child_pid = child.strip.to_i
67
+ q.push(child_pid)
68
+ pids << child_pid
69
+ end
70
+ end
71
+
72
+ pids
73
+ end
3
74
 
4
75
  def command_exists(command)
5
76
  checking_command = "checking command #{command} for existence\n"
@@ -118,6 +118,7 @@ module Debugger
118
118
  def debug_eval(str, b = get_binding)
119
119
  begin
120
120
  str = str.to_s
121
+ str.force_encoding('UTF-8') if(RUBY_VERSION > '2.0')
121
122
  to_inspect = Command.unescape_incoming(str)
122
123
  max_time = Debugger.evaluation_timeout
123
124
  @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time)
@@ -129,7 +129,7 @@ module Debugger
129
129
  locals = @state.context.frame_locals(@state.frame_pos)
130
130
  _self = @state.context.frame_self(@state.frame_pos)
131
131
  begin
132
- locals['self'] = _self unless "main" == _self.to_s
132
+ locals['self'] = _self unless TOPLEVEL_BINDING.eval('self') == _self
133
133
  rescue => ex
134
134
  locals['self'] = "<Cannot evaluate self>"
135
135
  $stderr << "Cannot evaluate self\n#{ex.class.name}: #{ex.message}\n #{ex.backtrace.join("\n ")}"
@@ -19,6 +19,11 @@ module Debugger
19
19
  'notify_dispatcher' => true
20
20
  )
21
21
 
22
+ if(options.ignore_port)
23
+ options.port = find_free_port(options.host)
24
+ options.notify_dispatcher = true
25
+ end
26
+
22
27
  start_debugger(options)
23
28
  end
24
29
 
@@ -39,7 +44,6 @@ module Debugger
39
44
  Debugger.keep_frame_binding = options.frame_bind
40
45
  Debugger.tracing = options.tracing
41
46
  Debugger.cli_debug = options.cli_debug
42
-
43
47
  Debugger.prepare_debugger(options)
44
48
  end
45
49
 
@@ -6,5 +6,6 @@ if ENV['IDE_PROCESS_DISPATCHER']
6
6
  end
7
7
  require 'ruby-debug-ide'
8
8
  require 'ruby-debug-ide/multiprocess'
9
+ Debugger::MultiProcess::do_monkey
9
10
  Debugger::MultiProcess::pre_child
10
11
  end
@@ -1,3 +1,3 @@
1
1
  module Debugger
2
- IDE_VERSION='0.6.1.beta4'
2
+ IDE_VERSION='0.6.1.beta6'
3
3
  end
@@ -1,12 +1,39 @@
1
1
  require 'stringio'
2
2
  require 'cgi'
3
3
  require 'monitor'
4
+ require 'objspace'
4
5
 
5
6
  module Debugger
6
7
 
8
+ module OverflowMessageType
9
+ NIL_MESSAGE = lambda {|e| nil}
10
+ EXCEPTION_MESSAGE = lambda {|e| e.message}
11
+ SPECIAL_SYMBOL_MESSAGE = lambda {|e| '<?>'}
12
+ end
13
+
14
+ class MemoryLimitError < StandardError
15
+ attr_reader :message
16
+ attr_reader :backtrace
17
+
18
+ def initialize(message, backtrace = '')
19
+ @message = message
20
+ @backtrace = backtrace
21
+ end
22
+ end
23
+
24
+ class TimeLimitError < StandardError
25
+ attr_reader :message
26
+ attr_reader :backtrace
27
+
28
+ def initialize(message, backtrace = '')
29
+ @message = message
30
+ @backtrace = backtrace
31
+ end
32
+ end
33
+
7
34
  class XmlPrinter # :nodoc:
8
35
  class ExceptionProxy
9
- instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$|^instance_variables$|^instance_eval$)/ }
36
+ instance_methods.each {|m| undef_method m unless m =~ /(^__|^send$|^object_id$|^instance_variables$|^instance_eval$)/}
10
37
 
11
38
  def initialize(exception)
12
39
  @exception = exception
@@ -14,9 +41,9 @@ module Debugger
14
41
  @backtrace = Debugger.cleanup_backtrace(exception.backtrace)
15
42
  end
16
43
 
17
- private
18
- def method_missing(called, *args, &block)
19
- @exception.__send__(called, *args, &block)
44
+ private
45
+ def method_missing(called, *args, &block)
46
+ @exception.__send__(called, *args, &block)
20
47
  end
21
48
  end
22
49
 
@@ -31,15 +58,15 @@ module Debugger
31
58
  end
32
59
  end
33
60
  }
34
- end
61
+ end
35
62
 
36
63
  @@monitor = Monitor.new
37
64
  attr_accessor :interface
38
-
65
+
39
66
  def initialize(interface)
40
67
  @interface = interface
41
68
  end
42
-
69
+
43
70
  def print_msg(*args)
44
71
  msg, *args = args
45
72
  xml_message = CGI.escapeHTML(msg % args)
@@ -62,7 +89,7 @@ module Debugger
62
89
  print CGI.escapeHTML(msg % args)
63
90
  end
64
91
  end
65
-
92
+
66
93
  def print_frames(context, current_frame_id)
67
94
  print_element("frames") do
68
95
  (0...context.stack_size).each do |id|
@@ -70,18 +97,18 @@ module Debugger
70
97
  end
71
98
  end
72
99
  end
73
-
100
+
74
101
  def print_current_frame(frame_pos)
75
102
  print_debug "Selected frame no #{frame_pos}"
76
103
  end
77
-
104
+
78
105
  def print_frame(context, frame_id, current_frame_id)
79
106
  # idx + 1: one-based numbering as classic-debugger
80
107
  file = context.frame_file(frame_id)
81
108
  print "<frame no=\"%s\" file=\"%s\" line=\"%s\" #{"current='true' " if frame_id == current_frame_id}/>",
82
- frame_id + 1, CGI.escapeHTML(File.expand_path(file)), context.frame_line(frame_id)
109
+ frame_id + 1, CGI.escapeHTML(File.expand_path(file)), context.frame_line(frame_id)
83
110
  end
84
-
111
+
85
112
  def print_contexts(contexts)
86
113
  print_element("threads") do
87
114
  contexts.each do |c|
@@ -89,11 +116,11 @@ module Debugger
89
116
  end
90
117
  end
91
118
  end
92
-
119
+
93
120
  def print_context(context)
94
121
  print "<thread id=\"%s\" status=\"%s\" pid=\"%s\" #{current_thread_attr(context)}/>", context.thnum, context.thread.status, Process.pid
95
122
  end
96
-
123
+
97
124
  def print_variables(vars, kind)
98
125
  print_element("variables") do
99
126
  # print self at top position
@@ -103,26 +130,26 @@ module Debugger
103
130
  end
104
131
  end
105
132
  end
106
-
133
+
107
134
  def print_array(array)
108
135
  print_element("variables") do
109
- index = 0
110
- array.each { |e|
111
- print_variable('[' + index.to_s + ']', e, 'instance')
112
- index += 1
136
+ index = 0
137
+ array.each {|e|
138
+ print_variable('[' + index.to_s + ']', e, 'instance')
139
+ index += 1
113
140
  }
114
141
  end
115
142
  end
116
-
143
+
117
144
  def print_hash(hash)
118
145
  print_element("variables") do
119
- hash.keys.each { | k |
146
+ hash.keys.each {|k|
120
147
  if k.class.name == "String"
121
148
  name = '\'' + k + '\''
122
149
  else
123
- name = k.to_s
150
+ name = exec_with_allocation_control(k, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :to_s, OverflowMessageType::EXCEPTION_MESSAGE)
124
151
  end
125
- print_variable(name, hash[k], 'instance')
152
+ print_variable(name, hash[k], 'instance')
126
153
  }
127
154
  end
128
155
  end
@@ -134,10 +161,55 @@ module Debugger
134
161
  InspectCommand.reference_result(bytes)
135
162
  print_variable('bytes', bytes, 'instance')
136
163
  end
137
- print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding')
164
+ print_variable('encoding', string.encoding, 'instance') if string.respond_to?('encoding')
138
165
  end
139
166
  end
140
-
167
+
168
+ def exec_with_allocation_control(value, memory_limit, time_limit, exec_method, overflow_message_type)
169
+ check_memory_limit = true
170
+ if (defined?(JRUBY_VERSION) || ENV['DEBUGGER_MEMORY_LIMIT'].to_i <= 0)
171
+ check_memory_limit = false
172
+ end
173
+ curr_thread = Thread.current
174
+ result = nil
175
+ inspect_thread = DebugThread.start {
176
+
177
+ start_alloc_size = ObjectSpace.memsize_of_all if (check_memory_limit)
178
+ start_time = Time.now.to_f
179
+
180
+ trace = TracePoint.new(:c_call, :call) do |tp|
181
+
182
+ if (rand > 0.75)
183
+ curr_time = Time.now.to_f
184
+
185
+ if ((curr_time - start_time) * 1e3 > time_limit)
186
+ curr_thread.raise TimeLimitError.new("Timeout: evaluation of #{exec_method} took longer than #{time_limit}ms.", "#{caller.map {|l| "\t#{l}"}.join("\n")}")
187
+ inspect_thread.kill
188
+ end
189
+
190
+ if (check_memory_limit)
191
+ curr_alloc_size = ObjectSpace.memsize_of_all
192
+ start_alloc_size = curr_alloc_size if (curr_alloc_size < start_alloc_size)
193
+
194
+ if (curr_alloc_size - start_alloc_size > 1e6 * memory_limit)
195
+ 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")}")
196
+ inspect_thread.kill
197
+ end
198
+ end
199
+ end
200
+ end.enable {
201
+ result = value.send exec_method
202
+ }
203
+ }
204
+ inspect_thread.join
205
+ inspect_thread.kill
206
+ return result
207
+ rescue MemoryLimitError, TimeLimitError => e
208
+ print_debug(e.message + "\n" + e.backtrace)
209
+
210
+ return overflow_message_type.call(e)
211
+ end
212
+
141
213
  def print_variable(name, value, kind)
142
214
  name = name.to_s
143
215
  if value.nil?
@@ -147,7 +219,7 @@ module Debugger
147
219
  if value.is_a?(Array) || value.is_a?(Hash)
148
220
  has_children = !value.empty?
149
221
  if has_children
150
- size = value.size
222
+ size = value.size
151
223
  value_str = "#{value.class} (#{value.size} element#{size > 1 ? "s" : "" })"
152
224
  else
153
225
  value_str = "Empty #{value.class}"
@@ -155,27 +227,29 @@ module Debugger
155
227
  elsif value.is_a?(String)
156
228
  has_children = value.respond_to?('bytes') || value.respond_to?('encoding')
157
229
  value_str = value
158
- else
230
+ else
159
231
  has_children = !value.instance_variables.empty? || !value.class.class_variables.empty?
160
- value_str = value.to_s || 'nil' rescue "<#to_s method raised exception: #{$!}>"
232
+
233
+ 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: #{$!}>"
234
+
161
235
  unless value_str.is_a?(String)
162
- value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String."
236
+ value_str = "ERROR: #{value.class}.to_s method returns #{value_str.class}. Should return String."
163
237
  end
164
238
  end
165
239
 
166
240
  if value_str.respond_to?('encode')
167
241
  # noinspection RubyEmptyRescueBlockInspection
168
242
  begin
169
- value_str = value_str.encode("UTF-8")
243
+ value_str = value_str.encode("UTF-8")
170
244
  rescue
171
245
  end
172
246
  end
173
247
  value_str = handle_binary_data(value_str)
174
248
  escaped_value_str = CGI.escapeHTML(value_str)
175
249
  print("<variable name=\"%s\" %s kind=\"%s\" %s type=\"%s\" hasChildren=\"%s\" objectId=\"%#+x\">",
176
- CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind,
177
- build_value_attr(escaped_value_str), value.class,
178
- has_children, value.respond_to?(:object_id) ? value.object_id : value.id)
250
+ CGI.escapeHTML(name), build_compact_value_attr(value, value_str), kind,
251
+ build_value_attr(escaped_value_str), value.class,
252
+ has_children, value.respond_to?(:object_id) ? value.object_id : value.id)
179
253
  print("<value><![CDATA[%s]]></value>", escaped_value_str) if Debugger.value_as_nested_element
180
254
  print('</variable>')
181
255
  rescue StandardError => e
@@ -198,28 +272,28 @@ module Debugger
198
272
 
199
273
  def print_breakpoints(breakpoints)
200
274
  print_element 'breakpoints' do
201
- breakpoints.sort_by{|b| b.id }.each do |b|
275
+ breakpoints.sort_by {|b| b.id}.each do |b|
202
276
  print "<breakpoint n=\"%d\" file=\"%s\" line=\"%s\" />", b.id, CGI.escapeHTML(b.source), b.pos.to_s
203
277
  end
204
278
  end
205
279
  end
206
-
280
+
207
281
  def print_breakpoint_added(b)
208
282
  print "<breakpointAdded no=\"%s\" location=\"%s:%s\"/>", b.id, CGI.escapeHTML(b.source), b.pos
209
283
  end
210
-
284
+
211
285
  def print_breakpoint_deleted(b)
212
286
  print "<breakpointDeleted no=\"%s\"/>", b.id
213
287
  end
214
-
288
+
215
289
  def print_breakpoint_enabled(b)
216
290
  print "<breakpointEnabled bp_id=\"%s\"/>", b.id
217
291
  end
218
-
292
+
219
293
  def print_breakpoint_disabled(b)
220
294
  print "<breakpointDisabled bp_id=\"%s\"/>", b.id
221
295
  end
222
-
296
+
223
297
  def print_contdition_set(bp_id)
224
298
  print "<conditionSet bp_id=\"%d\"/>", bp_id
225
299
  end
@@ -239,37 +313,37 @@ module Debugger
239
313
  def print_expressions(exps)
240
314
  print_element "expressions" do
241
315
  exps.each_with_index do |(exp, value), idx|
242
- print_expression(exp, value, idx+1)
316
+ print_expression(exp, value, idx + 1)
243
317
  end
244
318
  end unless exps.empty?
245
319
  end
246
-
320
+
247
321
  def print_expression(exp, value, idx)
248
322
  print "<dispay name=\"%s\" value=\"%s\" no=\"%d\" />", exp, value, idx
249
323
  end
250
324
 
251
325
  def print_expression_info(incomplete, prompt, indent)
252
326
  print "<expressionInfo incomplete=\"%s\" prompt=\"%s\" indent=\"%s\"></expressionInfo>",
253
- incomplete, CGI.escapeHTML(prompt), indent
327
+ incomplete, CGI.escapeHTML(prompt), indent
254
328
  end
255
-
329
+
256
330
  def print_eval(exp, value)
257
- print "<eval expression=\"%s\" value=\"%s\" />", CGI.escapeHTML(exp), value
331
+ print "<eval expression=\"%s\" value=\"%s\" />", CGI.escapeHTML(exp), value
258
332
  end
259
-
333
+
260
334
  def print_pp(value)
261
335
  print value
262
336
  end
263
-
337
+
264
338
  def print_list(b, e, file, line)
265
339
  print "[%d, %d] in %s\n", b, e, file
266
340
  if (lines = Debugger.source_for(file))
267
341
  b.upto(e) do |n|
268
- if n > 0 && lines[n-1]
342
+ if n > 0 && lines[n - 1]
269
343
  if n == line
270
- print "=> %d %s\n", n, lines[n-1].chomp
344
+ print "=> %d %s\n", n, lines[n - 1].chomp
271
345
  else
272
- print " %d %s\n", n, lines[n-1].chomp
346
+ print " %d %s\n", n, lines[n - 1].chomp
273
347
  end
274
348
  end
275
349
  end
@@ -277,7 +351,7 @@ module Debugger
277
351
  print "No source-file available for %s\n", file
278
352
  end
279
353
  end
280
-
354
+
281
355
  def print_methods(methods)
282
356
  print_element "methods" do
283
357
  methods.each do |method|
@@ -285,31 +359,31 @@ module Debugger
285
359
  end
286
360
  end
287
361
  end
288
-
362
+
289
363
  # Events
290
-
364
+
291
365
  def print_breakpoint(_, breakpoint)
292
366
  print("<breakpoint file=\"%s\" line=\"%s\" threadId=\"%d\"/>",
293
- CGI.escapeHTML(breakpoint.source), breakpoint.pos, Debugger.current_context.thnum)
367
+ CGI.escapeHTML(breakpoint.source), breakpoint.pos, Debugger.current_context.thnum)
294
368
  end
295
-
369
+
296
370
  def print_catchpoint(exception)
297
371
  context = Debugger.current_context
298
- print("<exception file=\"%s\" line=\"%s\" type=\"%s\" message=\"%s\" threadId=\"%d\"/>",
299
- CGI.escapeHTML(context.frame_file(0)), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum)
372
+ print("<exception file=\"%s\" line=\"%s\" type=\"%s\" message=\"%s\" threadId=\"%d\"/>",
373
+ CGI.escapeHTML(context.frame_file(0)), context.frame_line(0), exception.class, CGI.escapeHTML(exception.to_s), context.thnum)
300
374
  end
301
-
375
+
302
376
  def print_trace(context, file, line)
303
377
  Debugger::print_debug "trace: location=\"%s:%s\", threadId=%d", file, line, context.thnum
304
378
  # TBD: do we want to clog fronend with the <trace> elements? There are tons of them.
305
379
  # print "<trace file=\"%s\" line=\"%s\" threadId=\"%d\" />", file, line, context.thnum
306
380
  end
307
-
381
+
308
382
  def print_at_line(context, file, line)
309
383
  print "<suspended file=\"%s\" line=\"%s\" threadId=\"%d\" frames=\"%d\"/>",
310
384
  CGI.escapeHTML(File.expand_path(file)), line, context.thnum, context.stack_size
311
385
  end
312
-
386
+
313
387
  def print_exception(exception, _)
314
388
  print_element("variables") do
315
389
  proxy = ExceptionProxy.new(exception)
@@ -317,21 +391,21 @@ module Debugger
317
391
  print_variable('error', proxy, 'exception')
318
392
  end
319
393
  rescue Exception
320
- print "<processingException type=\"%s\" message=\"%s\"/>",
321
- exception.class, CGI.escapeHTML(exception.to_s)
394
+ print "<processingException type=\"%s\" message=\"%s\"/>",
395
+ exception.class, CGI.escapeHTML(exception.to_s)
322
396
  end
323
-
397
+
324
398
  def print_inspect(eval_result)
325
- print_element("variables") do
399
+ print_element("variables") do
326
400
  print_variable("eval_result", eval_result, 'local')
327
401
  end
328
402
  end
329
-
330
- def print_load_result(file, exception=nil)
403
+
404
+ def print_load_result(file, exception = nil)
331
405
  if exception
332
- print("<loadResult file=\"%s\" exceptionType=\"%s\" exceptionMessage=\"%s\"/>", file, exception.class, CGI.escapeHTML(exception.to_s))
406
+ print("<loadResult file=\"%s\" exceptionType=\"%s\" exceptionMessage=\"%s\"/>", file, exception.class, CGI.escapeHTML(exception.to_s))
333
407
  else
334
- print("<loadResult file=\"%s\" status=\"OK\"/>", file)
408
+ print("<loadResult file=\"%s\" status=\"OK\"/>", file)
335
409
  end
336
410
  end
337
411
 
@@ -345,7 +419,7 @@ module Debugger
345
419
  end
346
420
 
347
421
  private
348
-
422
+
349
423
  def print(*params)
350
424
  Debugger::print_debug(*params)
351
425
  @interface.print(*params)
@@ -381,22 +455,35 @@ module Debugger
381
455
  end
382
456
 
383
457
  def compact_array_str(value)
384
- slice = value[0..10]
385
- compact = slice.inspect
386
- if value.size != slice.size
387
- compact[0..compact.size-2] + ", ...]"
458
+ slice = value[0..10]
459
+
460
+ compact = exec_with_allocation_control(slice, ENV['DEBUGGER_MEMORY_LIMIT'].to_i, ENV['INSPECT_TIME_LIMIT'].to_i, :inspect, OverflowMessageType::NIL_MESSAGE)
461
+
462
+ if compact && value.size != slice.size
463
+ compact[0..compact.size - 2] + ", ...]"
388
464
  end
389
465
  compact
390
466
  end
391
467
 
392
468
  def compact_hash_str(value)
393
- slice = value.sort_by { |k, _| k.to_s }[0..5]
394
- compact = slice.map { |kv| "#{kv[0]}: #{handle_binary_data(kv[1])}" }.join(", ")
469
+ keys_strings = Hash.new
470
+
471
+ slice = value.sort_by do |k, _|
472
+ 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)
473
+ keys_strings[k] = keys_string
474
+ keys_string
475
+ end[0..5]
476
+
477
+ compact = slice.map do |kv|
478
+ key_string = keys_strings[kv[0]]
479
+ 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)
480
+ "#{key_string}: #{handle_binary_data(value_string)}"
481
+ end.join(", ")
395
482
  "{" + compact + (slice.size != value.size ? ", ..." : "") + "}"
396
483
  end
397
484
 
398
485
  def build_compact_value_attr(value, value_str)
399
- compact_value_str = build_compact_name(value, value_str)
486
+ compact_value_str = build_compact_name(value, value_str)
400
487
  compact_value_str.nil? ? '' : "compactValue=\"#{CGI.escapeHTML(compact_value_str)}\""
401
488
  end
402
489
 
@@ -422,7 +509,7 @@ module Debugger
422
509
  protect m
423
510
  end
424
511
  end
425
-
512
+
426
513
  end
427
514
 
428
515
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-debug-ide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1.beta4
4
+ version: 0.6.1.beta6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Barchfeld, Martin Krauskopf, Mark Moseley, JetBrains RubyMine Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-22 00:00:00.000000000 Z
11
+ date: 2017-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -24,8 +24,10 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.8.1
27
- description: |
28
- An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans and RubyMine.
27
+ description: 'An interface which glues ruby-debug to IDEs like Eclipse (RDT), NetBeans
28
+ and RubyMine.
29
+
30
+ '
29
31
  email: rubymine-feedback@jetbrains.com
30
32
  executables:
31
33
  - rdebug-ide
@@ -50,7 +52,6 @@ files:
50
52
  - lib/ruby-debug-ide/attach/native_debugger.rb
51
53
  - lib/ruby-debug-ide/attach/process_thread.rb
52
54
  - lib/ruby-debug-ide/attach/util.rb
53
- - lib/ruby-debug-ide/boo.sh
54
55
  - lib/ruby-debug-ide/command.rb
55
56
  - lib/ruby-debug-ide/commands/breakpoints.rb
56
57
  - lib/ruby-debug-ide/commands/catchpoint.rb
@@ -70,7 +71,6 @@ files:
70
71
  - lib/ruby-debug-ide/commands/threads.rb
71
72
  - lib/ruby-debug-ide/commands/variables.rb
72
73
  - lib/ruby-debug-ide/event_processor.rb
73
- - lib/ruby-debug-ide/foo.sh
74
74
  - lib/ruby-debug-ide/greeter.rb
75
75
  - lib/ruby-debug-ide/helper.rb
76
76
  - lib/ruby-debug-ide/ide_processor.rb
@@ -103,9 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
103
  version: 1.3.1
104
104
  requirements: []
105
105
  rubyforge_project: debug-commons
106
- rubygems_version: 2.4.8
106
+ rubygems_version: 2.6.11
107
107
  signing_key:
108
108
  specification_version: 4
109
109
  summary: IDE interface for ruby-debug.
110
110
  test_files: []
111
- has_rdoc: false
@@ -1 +0,0 @@
1
- sh foo.sh
@@ -1,4 +0,0 @@
1
- #!/bin/sh
2
- echo a;
3
- echo a;
4
- echo a