debug 1.1.0 → 1.2.3
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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
- data/.github/ISSUE_TEMPLATE/custom.md +10 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
- data/README.md +5 -0
- data/Rakefile +9 -6
- data/debug.gemspec +1 -1
- data/ext/debug/debug.c +5 -0
- data/lib/debug/breakpoint.rb +12 -3
- data/lib/debug/client.rb +33 -32
- data/lib/debug/color.rb +25 -3
- data/lib/debug/config.rb +26 -2
- data/lib/debug/console.rb +10 -2
- data/lib/debug/frame_info.rb +5 -5
- data/lib/debug/local.rb +21 -24
- data/lib/debug/server.rb +8 -7
- data/lib/debug/server_dap.rb +15 -13
- data/lib/debug/session.rb +206 -80
- data/lib/debug/thread_client.rb +22 -13
- data/lib/debug/tracer.rb +7 -2
- data/lib/debug/version.rb +1 -1
- metadata +11 -8
data/lib/debug/session.rb
CHANGED
|
@@ -86,7 +86,7 @@ module DEBUGGER__
|
|
|
86
86
|
# [:watch, ivar] => WatchIVarBreakpoint
|
|
87
87
|
# [:check, expr] => CheckBreakpoint
|
|
88
88
|
#
|
|
89
|
-
@tracers =
|
|
89
|
+
@tracers = {}
|
|
90
90
|
@th_clients = nil # {Thread => ThreadClient}
|
|
91
91
|
@q_evt = Queue.new
|
|
92
92
|
@displays = []
|
|
@@ -96,17 +96,22 @@ module DEBUGGER__
|
|
|
96
96
|
@postmortem_hook = nil
|
|
97
97
|
@postmortem = false
|
|
98
98
|
@thread_stopper = nil
|
|
99
|
+
@intercept_trap_sigint = false
|
|
100
|
+
@intercepted_sigint_cmd = 'DEFAULT'
|
|
99
101
|
|
|
100
102
|
@frame_map = {} # {id => [threadId, frame_depth]} for DAP
|
|
101
103
|
@var_map = {1 => [:globals], } # {id => ...} for DAP
|
|
102
104
|
@src_map = {} # {id => src}
|
|
103
105
|
|
|
106
|
+
@tp_thread_begin = nil
|
|
104
107
|
@tp_load_script = TracePoint.new(:script_compiled){|tp|
|
|
105
108
|
ThreadClient.current.on_load tp.instruction_sequence, tp.eval_script
|
|
106
109
|
}
|
|
107
110
|
@tp_load_script.enable
|
|
108
111
|
|
|
109
112
|
activate
|
|
113
|
+
|
|
114
|
+
self.postmortem = CONFIG[:postmortem]
|
|
110
115
|
end
|
|
111
116
|
|
|
112
117
|
def active?
|
|
@@ -117,40 +122,41 @@ module DEBUGGER__
|
|
|
117
122
|
@bps.has_key? [file, line]
|
|
118
123
|
end
|
|
119
124
|
|
|
120
|
-
def
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
def activate on_fork: false
|
|
126
|
+
@tp_thread_begin&.disable
|
|
127
|
+
@tp_thread_begin = nil
|
|
128
|
+
|
|
129
|
+
if on_fork
|
|
130
|
+
@ui.activate self, on_fork: true
|
|
131
|
+
else
|
|
132
|
+
@ui.activate self, on_fork: false
|
|
124
133
|
end
|
|
125
|
-
end
|
|
126
134
|
|
|
127
|
-
|
|
135
|
+
q = Queue.new
|
|
128
136
|
@session_server = Thread.new do
|
|
129
137
|
Thread.current.name = 'DEBUGGER__::SESSION@server'
|
|
130
138
|
Thread.current.abort_on_exception = true
|
|
131
|
-
session_server_main
|
|
132
|
-
end
|
|
133
139
|
|
|
134
|
-
|
|
140
|
+
# Thread management
|
|
141
|
+
setup_threads
|
|
142
|
+
thc = thread_client Thread.current
|
|
143
|
+
thc.is_management
|
|
135
144
|
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
if @ui.respond_to?(:reader_thread) && thc = thread_client(@ui.reader_thread)
|
|
146
|
+
thc.is_management
|
|
147
|
+
end
|
|
138
148
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
@
|
|
143
|
-
end
|
|
149
|
+
@tp_thread_begin = TracePoint.new(:thread_begin) do |tp|
|
|
150
|
+
thread_client
|
|
151
|
+
end
|
|
152
|
+
@tp_thread_begin.enable
|
|
144
153
|
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
# session start
|
|
155
|
+
q << true
|
|
156
|
+
session_server_main
|
|
147
157
|
end
|
|
148
158
|
|
|
149
|
-
|
|
150
|
-
th = Thread.current
|
|
151
|
-
ThreadClient.current.on_thread_begin th
|
|
152
|
-
}
|
|
153
|
-
@tp_thread_begin.enable
|
|
159
|
+
q.pop
|
|
154
160
|
end
|
|
155
161
|
|
|
156
162
|
def deactivate
|
|
@@ -160,14 +166,14 @@ module DEBUGGER__
|
|
|
160
166
|
@tp_thread_begin.disable
|
|
161
167
|
@bps.each{|k, bp| bp.disable}
|
|
162
168
|
@th_clients.each{|th, thc| thc.close}
|
|
163
|
-
@tracers.each{|t| t.disable}
|
|
169
|
+
@tracers.values.each{|t| t.disable}
|
|
164
170
|
@q_evt.close
|
|
165
171
|
@ui&.deactivate
|
|
166
172
|
@ui = nil
|
|
167
173
|
end
|
|
168
174
|
|
|
169
175
|
def reset_ui ui
|
|
170
|
-
@ui.
|
|
176
|
+
@ui.deactivate
|
|
171
177
|
@ui = ui
|
|
172
178
|
end
|
|
173
179
|
|
|
@@ -182,6 +188,13 @@ module DEBUGGER__
|
|
|
182
188
|
output.each{|str| @ui.puts str}
|
|
183
189
|
|
|
184
190
|
case ev
|
|
191
|
+
|
|
192
|
+
when :thread_begin # special event, tc is nil
|
|
193
|
+
th = ev_args.shift
|
|
194
|
+
q = ev_args.shift
|
|
195
|
+
on_thread_begin th
|
|
196
|
+
q << true
|
|
197
|
+
|
|
185
198
|
when :init
|
|
186
199
|
wait_command_loop tc
|
|
187
200
|
|
|
@@ -193,26 +206,25 @@ module DEBUGGER__
|
|
|
193
206
|
|
|
194
207
|
when :trace
|
|
195
208
|
trace_id, msg = ev_args
|
|
196
|
-
if t = @tracers.find{|t| t.object_id == trace_id}
|
|
209
|
+
if t = @tracers.values.find{|t| t.object_id == trace_id}
|
|
197
210
|
t.puts msg
|
|
198
211
|
end
|
|
199
212
|
tc << :continue
|
|
200
213
|
|
|
201
|
-
when :thread_begin
|
|
202
|
-
th = ev_args.shift
|
|
203
|
-
on_thread_begin th
|
|
204
|
-
@ui.event :thread_begin, th
|
|
205
|
-
tc << :continue
|
|
206
|
-
|
|
207
214
|
when :suspend
|
|
208
215
|
case ev_args.first
|
|
209
216
|
when :breakpoint
|
|
210
217
|
bp, i = bp_index ev_args[1]
|
|
211
|
-
@ui.event :suspend_bp, i, bp
|
|
218
|
+
@ui.event :suspend_bp, i, bp, tc.id
|
|
212
219
|
when :trap
|
|
213
|
-
@ui.event :suspend_trap, ev_args[1]
|
|
220
|
+
@ui.event :suspend_trap, sig = ev_args[1], tc.id
|
|
221
|
+
|
|
222
|
+
if sig == :SIGINT && (@intercepted_sigint_cmd.kind_of?(Proc) || @intercepted_sigint_cmd.kind_of?(String))
|
|
223
|
+
@ui.puts "#{@intercepted_sigint_cmd.inspect} is registerred as SIGINT handler."
|
|
224
|
+
@ui.puts "`sigint` command execute it."
|
|
225
|
+
end
|
|
214
226
|
else
|
|
215
|
-
@ui.event :suspended
|
|
227
|
+
@ui.event :suspended, tc.id
|
|
216
228
|
end
|
|
217
229
|
|
|
218
230
|
if @displays.empty?
|
|
@@ -246,8 +258,7 @@ module DEBUGGER__
|
|
|
246
258
|
obj_id = ev_args[1]
|
|
247
259
|
obj_inspect = ev_args[2]
|
|
248
260
|
opt = ev_args[3]
|
|
249
|
-
|
|
250
|
-
@ui.puts "Enable #{t.to_s}"
|
|
261
|
+
add_tracer ObjectTracer.new(@ui, obj_id, obj_inspect, **opt)
|
|
251
262
|
else
|
|
252
263
|
# ignore
|
|
253
264
|
end
|
|
@@ -432,6 +443,29 @@ module DEBUGGER__
|
|
|
432
443
|
when 'kill!'
|
|
433
444
|
exit! (arg || 1).to_i
|
|
434
445
|
|
|
446
|
+
# * `sigint`
|
|
447
|
+
# * Execute SIGINT handler registerred by the debuggee.
|
|
448
|
+
# * Note that this command should be used just after stop by `SIGINT`.
|
|
449
|
+
when 'sigint'
|
|
450
|
+
begin
|
|
451
|
+
case cmd = @intercepted_sigint_cmd
|
|
452
|
+
when nil, 'IGNORE', :IGNORE, 'DEFAULT', :DEFAULT
|
|
453
|
+
# ignore
|
|
454
|
+
when String
|
|
455
|
+
eval(cmd)
|
|
456
|
+
when Proc
|
|
457
|
+
cmd.call
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
@tc << :continue
|
|
461
|
+
restart_all_threads
|
|
462
|
+
|
|
463
|
+
rescue Exception => e
|
|
464
|
+
@ui.puts "Exception: #{e}"
|
|
465
|
+
@ui.puts e.backtrace.map{|line| " #{e}"}
|
|
466
|
+
return :retry
|
|
467
|
+
end
|
|
468
|
+
|
|
435
469
|
### Breakpoint
|
|
436
470
|
|
|
437
471
|
# * `b[reak]`
|
|
@@ -740,7 +774,7 @@ module DEBUGGER__
|
|
|
740
774
|
@ui.puts "not supported on the remote console."
|
|
741
775
|
return :retry
|
|
742
776
|
end
|
|
743
|
-
@tc << [:eval, :
|
|
777
|
+
@tc << [:eval, :irb]
|
|
744
778
|
|
|
745
779
|
# don't repeat irb command
|
|
746
780
|
@repl_prev_line = nil
|
|
@@ -778,32 +812,29 @@ module DEBUGGER__
|
|
|
778
812
|
case arg
|
|
779
813
|
when nil
|
|
780
814
|
@ui.puts 'Tracers:'
|
|
781
|
-
@tracers.each_with_index{|t, i|
|
|
815
|
+
@tracers.values.each_with_index{|t, i|
|
|
782
816
|
@ui.puts "* \##{i} #{t}"
|
|
783
817
|
}
|
|
784
818
|
@ui.puts
|
|
785
819
|
return :retry
|
|
786
820
|
|
|
787
821
|
when /\Aline\z/
|
|
788
|
-
|
|
789
|
-
@ui.puts "Enable #{t.to_s}"
|
|
822
|
+
add_tracer LineTracer.new(@ui, pattern: pattern, into: into)
|
|
790
823
|
return :retry
|
|
791
824
|
|
|
792
825
|
when /\Acall\z/
|
|
793
|
-
|
|
794
|
-
@ui.puts "Enable #{t.to_s}"
|
|
826
|
+
add_tracer CallTracer.new(@ui, pattern: pattern, into: into)
|
|
795
827
|
return :retry
|
|
796
828
|
|
|
797
829
|
when /\Aexception\z/
|
|
798
|
-
|
|
799
|
-
@ui.puts "Enable #{t.to_s}"
|
|
830
|
+
add_tracer ExceptionTracer.new(@ui, pattern: pattern, into: into)
|
|
800
831
|
return :retry
|
|
801
832
|
|
|
802
833
|
when /\Aobject\s+(.+)/
|
|
803
834
|
@tc << [:trace, :object, $1.strip, {pattern: pattern, into: into}]
|
|
804
835
|
|
|
805
836
|
when /\Aoff\s+(\d+)\z/
|
|
806
|
-
if t = @tracers[$1.to_i]
|
|
837
|
+
if t = @tracers.values[$1.to_i]
|
|
807
838
|
t.disable
|
|
808
839
|
@ui.puts "Disable #{t.to_s}"
|
|
809
840
|
else
|
|
@@ -812,7 +843,7 @@ module DEBUGGER__
|
|
|
812
843
|
return :retry
|
|
813
844
|
|
|
814
845
|
when /\Aoff(\s+(line|call|exception|object))?\z/
|
|
815
|
-
@tracers.each{|t|
|
|
846
|
+
@tracers.values.each{|t|
|
|
816
847
|
if $2.nil? || t.type == $2
|
|
817
848
|
t.disable
|
|
818
849
|
@ui.puts "Disable #{t.to_s}"
|
|
@@ -1190,6 +1221,20 @@ module DEBUGGER__
|
|
|
1190
1221
|
@ui.puts e.message
|
|
1191
1222
|
end
|
|
1192
1223
|
|
|
1224
|
+
# tracers
|
|
1225
|
+
|
|
1226
|
+
def add_tracer tracer
|
|
1227
|
+
# don't repeat commands that add tracers
|
|
1228
|
+
@repl_prev_line = nil
|
|
1229
|
+
if @tracers.has_key? tracer.key
|
|
1230
|
+
tracer.disable
|
|
1231
|
+
@ui.puts "Duplicated tracer: #{tracer}"
|
|
1232
|
+
else
|
|
1233
|
+
@tracers[tracer.key] = tracer
|
|
1234
|
+
@ui.puts "Enable #{tracer}"
|
|
1235
|
+
end
|
|
1236
|
+
end
|
|
1237
|
+
|
|
1193
1238
|
# threads
|
|
1194
1239
|
|
|
1195
1240
|
def update_thread_list
|
|
@@ -1242,10 +1287,6 @@ module DEBUGGER__
|
|
|
1242
1287
|
thread_list
|
|
1243
1288
|
end
|
|
1244
1289
|
|
|
1245
|
-
def thread_client_create th
|
|
1246
|
-
@th_clients[th] = ThreadClient.new((@tc_id += 1), @q_evt, Queue.new, th)
|
|
1247
|
-
end
|
|
1248
|
-
|
|
1249
1290
|
def setup_threads
|
|
1250
1291
|
@th_clients = {}
|
|
1251
1292
|
|
|
@@ -1256,18 +1297,38 @@ module DEBUGGER__
|
|
|
1256
1297
|
|
|
1257
1298
|
def on_thread_begin th
|
|
1258
1299
|
if @th_clients.has_key? th
|
|
1259
|
-
# OK
|
|
1260
|
-
else
|
|
1261
1300
|
# TODO: NG?
|
|
1301
|
+
else
|
|
1262
1302
|
thread_client_create th
|
|
1263
1303
|
end
|
|
1264
1304
|
end
|
|
1265
1305
|
|
|
1266
|
-
def
|
|
1267
|
-
|
|
1268
|
-
|
|
1306
|
+
private def thread_client_create th
|
|
1307
|
+
# TODO: Ractor support
|
|
1308
|
+
raise "Only session_server can create thread_client" unless Thread.current == @session_server
|
|
1309
|
+
@th_clients[th] = ThreadClient.new((@tc_id += 1), @q_evt, Queue.new, th)
|
|
1310
|
+
end
|
|
1311
|
+
|
|
1312
|
+
private def ask_thread_client th = Thread.current
|
|
1313
|
+
# TODO: Ractor support
|
|
1314
|
+
q2 = Queue.new
|
|
1315
|
+
# tc, output, ev, @internal_info, *ev_args = evt
|
|
1316
|
+
@q_evt << [nil, [], :thread_begin, nil, th, q2]
|
|
1317
|
+
q2.pop
|
|
1318
|
+
|
|
1319
|
+
@th_clients[th] or raise "unexpected error"
|
|
1320
|
+
end
|
|
1321
|
+
|
|
1322
|
+
# can be called by other threads
|
|
1323
|
+
def thread_client th = Thread.current
|
|
1324
|
+
if @th_clients.has_key? th
|
|
1325
|
+
@th_clients[th]
|
|
1269
1326
|
else
|
|
1270
|
-
|
|
1327
|
+
if Thread.current == @session_server
|
|
1328
|
+
thread_client_create th
|
|
1329
|
+
else
|
|
1330
|
+
ask_thread_client th
|
|
1331
|
+
end
|
|
1271
1332
|
end
|
|
1272
1333
|
end
|
|
1273
1334
|
|
|
@@ -1386,7 +1447,10 @@ module DEBUGGER__
|
|
|
1386
1447
|
end
|
|
1387
1448
|
end
|
|
1388
1449
|
|
|
1389
|
-
def enter_postmortem_session
|
|
1450
|
+
def enter_postmortem_session exc
|
|
1451
|
+
return unless exc.instance_variable_defined? :@__debugger_postmortem_frames
|
|
1452
|
+
|
|
1453
|
+
frames = exc.instance_variable_get(:@__debugger_postmortem_frames)
|
|
1390
1454
|
@postmortem = true
|
|
1391
1455
|
ThreadClient.current.suspend :postmortem, postmortem_frames: frames
|
|
1392
1456
|
ensure
|
|
@@ -1399,7 +1463,7 @@ module DEBUGGER__
|
|
|
1399
1463
|
@postmortem_hook = TracePoint.new(:raise){|tp|
|
|
1400
1464
|
exc = tp.raised_exception
|
|
1401
1465
|
frames = DEBUGGER__.capture_frames(__dir__)
|
|
1402
|
-
exc.instance_variable_set(:@
|
|
1466
|
+
exc.instance_variable_set(:@__debugger_postmortem_frames, frames)
|
|
1403
1467
|
}
|
|
1404
1468
|
at_exit{
|
|
1405
1469
|
@postmortem_hook.disable
|
|
@@ -1411,7 +1475,7 @@ module DEBUGGER__
|
|
|
1411
1475
|
@ui.puts exc.backtrace.map{|e| ' ' + e}
|
|
1412
1476
|
@ui.puts "\n"
|
|
1413
1477
|
|
|
1414
|
-
enter_postmortem_session exc
|
|
1478
|
+
enter_postmortem_session exc
|
|
1415
1479
|
rescue SystemExit
|
|
1416
1480
|
exit!
|
|
1417
1481
|
rescue Exception => e
|
|
@@ -1431,6 +1495,30 @@ module DEBUGGER__
|
|
|
1431
1495
|
end
|
|
1432
1496
|
end
|
|
1433
1497
|
end
|
|
1498
|
+
|
|
1499
|
+
def save_int_trap cmd
|
|
1500
|
+
prev, @intercepted_sigint_cmd = @intercepted_sigint_cmd, cmd
|
|
1501
|
+
prev
|
|
1502
|
+
end
|
|
1503
|
+
|
|
1504
|
+
attr_reader :intercepted_sigint_cmd
|
|
1505
|
+
|
|
1506
|
+
def intercept_trap_sigint?
|
|
1507
|
+
@intercept_trap_sigint
|
|
1508
|
+
end
|
|
1509
|
+
|
|
1510
|
+
def intercept_trap_sigint flag, &b
|
|
1511
|
+
prev = @intercept_trap_sigint
|
|
1512
|
+
@intercept_trap_sigint = flag
|
|
1513
|
+
yield
|
|
1514
|
+
ensure
|
|
1515
|
+
@intercept_trap_sigint = prev
|
|
1516
|
+
end
|
|
1517
|
+
|
|
1518
|
+
def intercept_trap_sigint_start prev
|
|
1519
|
+
@intercept_trap_sigint = true
|
|
1520
|
+
@intercepted_sigint_cmd = prev
|
|
1521
|
+
end
|
|
1434
1522
|
end
|
|
1435
1523
|
|
|
1436
1524
|
class UI_Base
|
|
@@ -1526,6 +1614,9 @@ module DEBUGGER__
|
|
|
1526
1614
|
def self.setup_initial_suspend
|
|
1527
1615
|
if !CONFIG[:nonstop]
|
|
1528
1616
|
case
|
|
1617
|
+
when CONFIG[:stop_at_load]
|
|
1618
|
+
add_line_breakpoint __FILE__, __LINE__ + 1, oneshot: true, hook_call: false
|
|
1619
|
+
nil # stop here
|
|
1529
1620
|
when path = ENV['RUBY_DEBUG_INITIAL_SUSPEND_PATH']
|
|
1530
1621
|
add_line_breakpoint path, 0, oneshot: true, hook_call: false
|
|
1531
1622
|
when loc = ::DEBUGGER__.require_location
|
|
@@ -1643,7 +1734,18 @@ module DEBUGGER__
|
|
|
1643
1734
|
|
|
1644
1735
|
at_exit{
|
|
1645
1736
|
trap(:SIGINT, :IGNORE)
|
|
1646
|
-
|
|
1737
|
+
|
|
1738
|
+
# only check child process from its parent
|
|
1739
|
+
if Process.pid == parent_pid
|
|
1740
|
+
begin
|
|
1741
|
+
# sending a null signal to see if the child is still alive
|
|
1742
|
+
Process.kill(0, child_pid)
|
|
1743
|
+
# if the child is still alive, wait for it
|
|
1744
|
+
Process.waitpid(child_pid)
|
|
1745
|
+
rescue Errno::ESRCH
|
|
1746
|
+
# if the child process has died, do nothing
|
|
1747
|
+
end
|
|
1748
|
+
end
|
|
1647
1749
|
}
|
|
1648
1750
|
}
|
|
1649
1751
|
child_hook = -> {
|
|
@@ -1675,8 +1777,36 @@ module DEBUGGER__
|
|
|
1675
1777
|
end
|
|
1676
1778
|
end
|
|
1677
1779
|
|
|
1678
|
-
|
|
1679
|
-
|
|
1780
|
+
module TrapInterceptor
|
|
1781
|
+
def trap sig, *command, &command_proc
|
|
1782
|
+
case sig&.to_sym
|
|
1783
|
+
when :INT, :SIGINT
|
|
1784
|
+
if defined?(SESSION) && SESSION.active? && SESSION.intercept_trap_sigint?
|
|
1785
|
+
return SESSION.save_int_trap(command.empty? ? command_proc : command.first)
|
|
1786
|
+
end
|
|
1787
|
+
end
|
|
1788
|
+
|
|
1789
|
+
super
|
|
1790
|
+
end
|
|
1791
|
+
end
|
|
1792
|
+
|
|
1793
|
+
if RUBY_VERSION >= '3.0.0'
|
|
1794
|
+
module ::Kernel
|
|
1795
|
+
prepend ForkInterceptor
|
|
1796
|
+
prepend TrapInterceptor
|
|
1797
|
+
end
|
|
1798
|
+
else
|
|
1799
|
+
class ::Object
|
|
1800
|
+
include ForkInterceptor
|
|
1801
|
+
include TrapInterceptor
|
|
1802
|
+
end
|
|
1803
|
+
end
|
|
1804
|
+
|
|
1805
|
+
module ::Kernel
|
|
1806
|
+
class << self
|
|
1807
|
+
prepend ForkInterceptor
|
|
1808
|
+
prepend TrapInterceptor
|
|
1809
|
+
end
|
|
1680
1810
|
end
|
|
1681
1811
|
|
|
1682
1812
|
module ::Process
|
|
@@ -1684,10 +1814,16 @@ module DEBUGGER__
|
|
|
1684
1814
|
prepend ForkInterceptor
|
|
1685
1815
|
end
|
|
1686
1816
|
end
|
|
1817
|
+
|
|
1818
|
+
module ::Signal
|
|
1819
|
+
class << self
|
|
1820
|
+
prepend TrapInterceptor
|
|
1821
|
+
end
|
|
1822
|
+
end
|
|
1687
1823
|
end
|
|
1688
1824
|
|
|
1689
|
-
|
|
1690
|
-
def
|
|
1825
|
+
module Kernel
|
|
1826
|
+
def debugger pre: nil, do: nil
|
|
1691
1827
|
return if !defined?(::DEBUGGER__::SESSION) || !::DEBUGGER__::SESSION.active?
|
|
1692
1828
|
|
|
1693
1829
|
if pre || (do_expr = binding.local_variable_get(:do))
|
|
@@ -1697,20 +1833,10 @@ class Binding
|
|
|
1697
1833
|
::DEBUGGER__.add_line_breakpoint __FILE__, __LINE__ + 1, oneshot: true, command: cmds
|
|
1698
1834
|
self
|
|
1699
1835
|
end
|
|
1700
|
-
alias b break
|
|
1701
1836
|
end
|
|
1702
1837
|
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
def debugger(...)
|
|
1707
|
-
binding.break(...)
|
|
1708
|
-
end
|
|
1709
|
-
RUBY
|
|
1710
|
-
else
|
|
1711
|
-
def debugger pre: nil, do: nil
|
|
1712
|
-
b = binding
|
|
1713
|
-
b.break pre: pre, do: b.local_variable_get(:do)
|
|
1714
|
-
end
|
|
1715
|
-
end
|
|
1838
|
+
class Binding
|
|
1839
|
+
alias break debugger
|
|
1840
|
+
alias b debugger
|
|
1716
1841
|
end
|
|
1842
|
+
|
data/lib/debug/thread_client.rb
CHANGED
|
@@ -20,9 +20,11 @@ module DEBUGGER__
|
|
|
20
20
|
|
|
21
21
|
class ThreadClient
|
|
22
22
|
def self.current
|
|
23
|
-
Thread.current[:DEBUGGER__ThreadClient]
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
if thc = Thread.current[:DEBUGGER__ThreadClient]
|
|
24
|
+
thc
|
|
25
|
+
else
|
|
26
|
+
thc = SESSION.thread_client
|
|
27
|
+
Thread.current[:DEBUGGER__ThreadClient] = thc
|
|
26
28
|
end
|
|
27
29
|
end
|
|
28
30
|
|
|
@@ -115,7 +117,7 @@ module DEBUGGER__
|
|
|
115
117
|
# TODO: there is waiting -> waiting
|
|
116
118
|
# raise "#{mode} is given, but #{mode}" unless self.running?
|
|
117
119
|
else
|
|
118
|
-
raise
|
|
120
|
+
raise "unknown mode: #{mode}"
|
|
119
121
|
end
|
|
120
122
|
|
|
121
123
|
@mode = mode
|
|
@@ -138,7 +140,11 @@ module DEBUGGER__
|
|
|
138
140
|
end
|
|
139
141
|
|
|
140
142
|
def inspect
|
|
141
|
-
|
|
143
|
+
if bt = @thread.backtrace
|
|
144
|
+
"#<DBG:TC #{self.id}:#{@mode}@#{bt[-1]}>"
|
|
145
|
+
else # bt can be nil
|
|
146
|
+
"#<DBG:TC #{self.id}:#{@mode}>"
|
|
147
|
+
end
|
|
142
148
|
end
|
|
143
149
|
|
|
144
150
|
def to_s
|
|
@@ -194,10 +200,6 @@ module DEBUGGER__
|
|
|
194
200
|
wait_next_action
|
|
195
201
|
end
|
|
196
202
|
|
|
197
|
-
def on_thread_begin th
|
|
198
|
-
wait_reply [:thread_begin, th]
|
|
199
|
-
end
|
|
200
|
-
|
|
201
203
|
def on_load iseq, eval_src
|
|
202
204
|
wait_reply [:load, iseq, eval_src]
|
|
203
205
|
end
|
|
@@ -340,7 +342,8 @@ module DEBUGGER__
|
|
|
340
342
|
begin
|
|
341
343
|
@success_last_eval = false
|
|
342
344
|
|
|
343
|
-
b = current_frame
|
|
345
|
+
b = current_frame&.eval_binding || TOPLEVEL_BINDING
|
|
346
|
+
|
|
344
347
|
result = if b
|
|
345
348
|
f, _l = b.source_location
|
|
346
349
|
b.eval(src, "(rdbg)/#{f}")
|
|
@@ -659,18 +662,17 @@ module DEBUGGER__
|
|
|
659
662
|
|
|
660
663
|
def wait_next_action_
|
|
661
664
|
# assertions
|
|
662
|
-
raise "@mode is #{@mode}"
|
|
665
|
+
raise "@mode is #{@mode}" if !waiting?
|
|
663
666
|
|
|
664
667
|
unless SESSION.active?
|
|
665
668
|
pp caller
|
|
666
669
|
set_mode :running
|
|
667
670
|
return
|
|
668
671
|
end
|
|
669
|
-
# SESSION.check_forked
|
|
670
672
|
|
|
671
673
|
while true
|
|
672
674
|
begin
|
|
673
|
-
set_mode :waiting if
|
|
675
|
+
set_mode :waiting if !waiting?
|
|
674
676
|
cmds = @q_cmd.pop
|
|
675
677
|
# pp [self, cmds: cmds]
|
|
676
678
|
break unless cmds
|
|
@@ -779,6 +781,13 @@ module DEBUGGER__
|
|
|
779
781
|
end
|
|
780
782
|
when :call
|
|
781
783
|
result = frame_eval(eval_src)
|
|
784
|
+
when :irb
|
|
785
|
+
begin
|
|
786
|
+
result = frame_eval('binding.irb')
|
|
787
|
+
ensure
|
|
788
|
+
# workaround: https://github.com/ruby/debug/issues/308
|
|
789
|
+
Reline.prompt_proc = nil if defined? Reline
|
|
790
|
+
end
|
|
782
791
|
when :display, :try_display
|
|
783
792
|
failed_results = []
|
|
784
793
|
eval_src.each_with_index{|src, i|
|
data/lib/debug/tracer.rb
CHANGED
|
@@ -14,7 +14,7 @@ module DEBUGGER__
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
attr_reader :type
|
|
17
|
+
attr_reader :type, :key
|
|
18
18
|
|
|
19
19
|
def initialize ui, pattern: nil, into: nil
|
|
20
20
|
if /\ADEBUGGER__::(([A-Z][a-z]+?)[A-Z][a-z]+)/ =~ self.class.name
|
|
@@ -37,6 +37,8 @@ module DEBUGGER__
|
|
|
37
37
|
@output = ui
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
@key = [@type, @pattern, @into].freeze
|
|
41
|
+
|
|
40
42
|
enable
|
|
41
43
|
end
|
|
42
44
|
|
|
@@ -95,6 +97,8 @@ module DEBUGGER__
|
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
def minfo tp
|
|
100
|
+
return "block{}" if tp.event == :b_call
|
|
101
|
+
|
|
98
102
|
klass = tp.defined_class
|
|
99
103
|
|
|
100
104
|
if klass.singleton_class?
|
|
@@ -172,6 +176,7 @@ module DEBUGGER__
|
|
|
172
176
|
@obj_id = obj_id
|
|
173
177
|
@obj_inspect = obj_inspect
|
|
174
178
|
super(ui, **kw)
|
|
179
|
+
@key = [@type, @obj_id, @pattern, @into].freeze
|
|
175
180
|
end
|
|
176
181
|
|
|
177
182
|
def description
|
|
@@ -201,7 +206,7 @@ module DEBUGGER__
|
|
|
201
206
|
end
|
|
202
207
|
|
|
203
208
|
out tp, " #{colorized_obj_inspect} receives #{colorize_blue(method_info)}"
|
|
204
|
-
|
|
209
|
+
elsif !tp.parameters.empty?
|
|
205
210
|
b = tp.binding
|
|
206
211
|
method_info = colorize_blue(minfo(tp))
|
|
207
212
|
|
data/lib/debug/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: debug
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Koichi Sasada
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-10-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: irb
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 1.3.6
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 1.3.6
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: reline
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -48,6 +48,9 @@ extensions:
|
|
|
48
48
|
- ext/debug/extconf.rb
|
|
49
49
|
extra_rdoc_files: []
|
|
50
50
|
files:
|
|
51
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
|
52
|
+
- ".github/ISSUE_TEMPLATE/custom.md"
|
|
53
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
|
51
54
|
- ".github/workflows/ruby.yml"
|
|
52
55
|
- ".gitignore"
|
|
53
56
|
- CONTRIBUTING.md
|
|
@@ -91,7 +94,7 @@ licenses:
|
|
|
91
94
|
metadata:
|
|
92
95
|
homepage_uri: https://github.com/ruby/debug
|
|
93
96
|
source_code_uri: https://github.com/ruby/debug
|
|
94
|
-
post_install_message:
|
|
97
|
+
post_install_message:
|
|
95
98
|
rdoc_options: []
|
|
96
99
|
require_paths:
|
|
97
100
|
- lib
|
|
@@ -106,8 +109,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
106
109
|
- !ruby/object:Gem::Version
|
|
107
110
|
version: '0'
|
|
108
111
|
requirements: []
|
|
109
|
-
rubygems_version: 3.
|
|
110
|
-
signing_key:
|
|
112
|
+
rubygems_version: 3.2.15
|
|
113
|
+
signing_key:
|
|
111
114
|
specification_version: 4
|
|
112
115
|
summary: Debugging functionality for Ruby
|
|
113
116
|
test_files: []
|