debug 1.0.0.beta5 → 1.0.0.beta6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +193 -2
- data/README.md +20 -12
- data/bin/gentest +22 -0
- data/exe/rdbg +9 -13
- data/lib/debug.rb +3 -0
- data/lib/debug/breakpoint.rb +11 -0
- data/lib/debug/client.rb +5 -7
- data/lib/debug/color.rb +5 -3
- data/lib/debug/config.rb +25 -13
- data/lib/debug/console.rb +13 -0
- data/lib/debug/frame_info.rb +2 -1
- data/lib/debug/open.rb +1 -0
- data/lib/debug/run.rb +3 -2
- data/lib/debug/server.rb +25 -16
- data/lib/debug/server_dap.rb +4 -2
- data/lib/debug/session.rb +140 -64
- data/lib/debug/source_repository.rb +2 -0
- data/lib/debug/thread_client.rb +43 -31
- data/lib/debug/version.rb +3 -1
- data/misc/README.md.erb +13 -9
- metadata +3 -3
- data/lib/debug/test_console.rb +0 -0
data/lib/debug/config.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module DEBUGGER__
|
3
4
|
def self.unix_domain_socket_dir
|
@@ -34,15 +35,18 @@ module DEBUGGER__
|
|
34
35
|
nonstop: 'RUBY_DEBUG_NONSTOP', # Nonstop mode ('1' is nonstop)
|
35
36
|
init_script: 'RUBY_DEBUG_INIT_SCRIPT', # debug command script path loaded at first stop
|
36
37
|
commands: 'RUBY_DEBUG_COMMANDS', # debug commands invoked at first stop. commands should be separated by ';;'
|
38
|
+
no_rc: 'RUBY_DEBUG_NO_RC', # ignore loading ~/.rdbgrc(.rb)
|
37
39
|
|
38
40
|
# UI setting
|
39
41
|
show_src_lines: 'RUBY_DEBUG_SHOW_SRC_LINES', # Show n lines source code on breakpoint (default: 10 lines).
|
40
42
|
show_frames: 'RUBY_DEBUG_SHOW_FRAMES', # Show n frames on breakpoint (default: 2 frames).
|
41
43
|
use_short_path: 'RUBY_DEBUG_USE_SHORT_PATH', # Show shoten PATH (like $(Gem)/foo.rb).
|
42
44
|
skip_nosrc: 'RUBY_DEBUG_SKIP_NOSRC', # Skip on no source code lines (default: false).
|
43
|
-
|
45
|
+
no_color: 'RUBY_DEBUG_NO_COLOR', # Do not use colorize
|
46
|
+
no_sigint_hook: 'RUBY_DEBUG_NO_SIGINT_HOOK', # Do not suspend on SIGINT
|
47
|
+
quiet: 'RUBY_DEBUG_QUIET', # Do not show messages
|
44
48
|
|
45
|
-
# remote
|
49
|
+
# remote setting
|
46
50
|
port: 'RUBY_DEBUG_PORT', # TCP/IP remote debugging: port
|
47
51
|
host: 'RUBY_DEBUG_HOST', # TCP/IP remote debugging: host (localhost if not given)
|
48
52
|
sock_path: 'RUBY_DEBUG_SOCK_PATH', # UNIX Domain Socket remote debugging: socket path
|
@@ -50,16 +54,15 @@ module DEBUGGER__
|
|
50
54
|
cookie: 'RUBY_DEBUG_COOKIE', # Cookie for negotiation
|
51
55
|
}.freeze
|
52
56
|
|
53
|
-
def self.
|
54
|
-
CONFIG_MAP.
|
55
|
-
|
57
|
+
def self.config_to_env_hash config
|
58
|
+
CONFIG_MAP.each_with_object({}){|(key, evname), env|
|
59
|
+
env[evname] = config[key].to_s if config[key]
|
56
60
|
}
|
57
61
|
end
|
58
62
|
|
59
63
|
def self.parse_argv argv
|
60
64
|
config = {
|
61
65
|
mode: :start,
|
62
|
-
use_colorize: true,
|
63
66
|
}
|
64
67
|
CONFIG_MAP.each{|key, evname|
|
65
68
|
if val = ENV[evname]
|
@@ -90,14 +93,26 @@ module DEBUGGER__
|
|
90
93
|
config[:nonstop] = '1'
|
91
94
|
end
|
92
95
|
|
93
|
-
o.on('-e COMMAND', '
|
96
|
+
o.on('-e COMMAND', 'Execute debug command at the beginning of the script.') do |cmd|
|
94
97
|
config[:commands] ||= ''
|
95
|
-
config[:commands]
|
98
|
+
config[:commands] += cmd + ';;'
|
96
99
|
end
|
97
100
|
|
98
|
-
o.on('-x FILE', '--init-script=FILE', '
|
101
|
+
o.on('-x FILE', '--init-script=FILE', 'Execute debug command in the FILE.') do |file|
|
99
102
|
config[:init_script] = file
|
100
103
|
end
|
104
|
+
o.on('--no-rc', 'Ignore ~/.rdbgrc') do
|
105
|
+
config[:no_rc] = true
|
106
|
+
end
|
107
|
+
o.on('--no-color', 'Disable colorize') do
|
108
|
+
config[:no_color] = true
|
109
|
+
end
|
110
|
+
|
111
|
+
o.on('-c', '--command', 'Enable command mode.',
|
112
|
+
'The first argument should be a command name in $PATH.',
|
113
|
+
'Example: \'rdbg -c bundle exec rake test\'') do
|
114
|
+
config[:command] = true
|
115
|
+
end
|
101
116
|
|
102
117
|
o.separator ''
|
103
118
|
|
@@ -154,11 +169,8 @@ module DEBUGGER__
|
|
154
169
|
exit
|
155
170
|
end
|
156
171
|
|
157
|
-
o.on('-c', '--command', 'Command mode (first argument is command name)') do
|
158
|
-
config[:command] = true
|
159
|
-
end
|
160
|
-
|
161
172
|
o.on('--util=NAME', 'Utility mode (used by tools)') do |name|
|
173
|
+
require_relative 'client'
|
162
174
|
Client.new(name)
|
163
175
|
exit
|
164
176
|
end
|
data/lib/debug/console.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'session'
|
2
4
|
return unless defined?(DEBUGGER__)
|
3
5
|
|
@@ -6,6 +8,17 @@ require 'io/console/size'
|
|
6
8
|
module DEBUGGER__
|
7
9
|
class UI_Console < UI_Base
|
8
10
|
def initialize
|
11
|
+
unless CONFIG[:no_sigint_hook]
|
12
|
+
@prev_handler = trap(:SIGINT){
|
13
|
+
ThreadClient.current.on_trap :SIGINT
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def close
|
19
|
+
if @prev_handler
|
20
|
+
trap(:SIGINT, @prev_handler)
|
21
|
+
end
|
9
22
|
end
|
10
23
|
|
11
24
|
def remote?
|
data/lib/debug/frame_info.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module DEBUGGER__
|
3
4
|
FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :frame_depth,
|
@@ -9,7 +10,7 @@ module DEBUGGER__
|
|
9
10
|
if File.exist? File.join(__dir__, 'debug.so')
|
10
11
|
require_relative 'debug.so'
|
11
12
|
else
|
12
|
-
|
13
|
+
require_relative 'debug'
|
13
14
|
end
|
14
15
|
|
15
16
|
class FrameInfo
|
data/lib/debug/open.rb
CHANGED
data/lib/debug/run.rb
CHANGED
data/lib/debug/server.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'socket'
|
2
4
|
|
3
5
|
require_relative 'session'
|
@@ -13,8 +15,8 @@ module DEBUGGER__
|
|
13
15
|
@accept_m = Mutex.new
|
14
16
|
@accept_cv = ConditionVariable.new
|
15
17
|
@client_addr = nil
|
16
|
-
@q_msg =
|
17
|
-
@q_ans =
|
18
|
+
@q_msg = nil
|
19
|
+
@q_ans = nil
|
18
20
|
@unsent_messages = []
|
19
21
|
@width = 80
|
20
22
|
|
@@ -23,7 +25,7 @@ module DEBUGGER__
|
|
23
25
|
Thread.current.abort_on_exception = true
|
24
26
|
|
25
27
|
accept do |server|
|
26
|
-
DEBUGGER__.
|
28
|
+
DEBUGGER__.warn "Connected."
|
27
29
|
|
28
30
|
@accept_m.synchronize{
|
29
31
|
@sock = server
|
@@ -36,6 +38,9 @@ module DEBUGGER__
|
|
36
38
|
@sock.puts m
|
37
39
|
}
|
38
40
|
@unsent_messages.clear
|
41
|
+
|
42
|
+
@q_msg = Queue.new
|
43
|
+
@q_ans = Queue.new
|
39
44
|
}
|
40
45
|
|
41
46
|
setup_interrupt do
|
@@ -43,12 +48,14 @@ module DEBUGGER__
|
|
43
48
|
end
|
44
49
|
|
45
50
|
rescue => e
|
46
|
-
DEBUGGER__.
|
51
|
+
DEBUGGER__.warn "ReaderThreadError: #{e}", :error
|
47
52
|
ensure
|
48
|
-
DEBUGGER__.
|
53
|
+
DEBUGGER__.warn "Disconnected."
|
49
54
|
@sock = nil
|
50
55
|
@q_msg.close
|
56
|
+
@q_msg = nil
|
51
57
|
@q_ans.close
|
58
|
+
@q_ans = nil
|
52
59
|
end
|
53
60
|
end
|
54
61
|
end
|
@@ -81,9 +88,6 @@ module DEBUGGER__
|
|
81
88
|
end
|
82
89
|
|
83
90
|
def process
|
84
|
-
@q_msg = Queue.new
|
85
|
-
@q_ans = Queue.new
|
86
|
-
|
87
91
|
pause
|
88
92
|
|
89
93
|
while line = @sock.gets
|
@@ -141,12 +145,20 @@ module DEBUGGER__
|
|
141
145
|
if s = @sock # already connection
|
142
146
|
# ok
|
143
147
|
elsif skip == true # skip process
|
144
|
-
|
148
|
+
no_sock = true
|
149
|
+
r = @accept_m.synchronize do
|
150
|
+
if @sock
|
151
|
+
no_sock = false
|
152
|
+
else
|
153
|
+
yield nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
return r if no_sock
|
145
157
|
else # wait for connection
|
146
158
|
until s = @sock
|
147
159
|
@accept_m.synchronize{
|
148
160
|
unless @sock
|
149
|
-
DEBUGGER__.
|
161
|
+
DEBUGGER__.warn "wait for debuger connection..."
|
150
162
|
@accept_cv.wait(@accept_m)
|
151
163
|
end
|
152
164
|
}
|
@@ -190,6 +202,7 @@ module DEBUGGER__
|
|
190
202
|
def readline
|
191
203
|
(sock do |s|
|
192
204
|
s.puts "input"
|
205
|
+
sleep 0.01 until @q_msg
|
193
206
|
@q_msg.pop
|
194
207
|
end || 'continue').strip
|
195
208
|
end
|
@@ -224,7 +237,7 @@ module DEBUGGER__
|
|
224
237
|
|
225
238
|
def accept
|
226
239
|
Socket.tcp_server_sockets @host, @port do |socks|
|
227
|
-
::DEBUGGER__.
|
240
|
+
::DEBUGGER__.warn "Debugger can attach via TCP/IP (#{socks.map{|e| e.local_address.inspect}})"
|
228
241
|
Socket.accept_loop(socks) do |sock, client|
|
229
242
|
@client_addr = client
|
230
243
|
yield sock
|
@@ -254,7 +267,7 @@ module DEBUGGER__
|
|
254
267
|
@sock_path = DEBUGGER__.create_unix_domain_socket_name(@sock_dir)
|
255
268
|
end
|
256
269
|
|
257
|
-
::DEBUGGER__.
|
270
|
+
::DEBUGGER__.warn "Debugger can attach via UNIX domain socket (#{@sock_path})"
|
258
271
|
Socket.unix_server_loop @sock_path do |sock, client|
|
259
272
|
@client_addr = client
|
260
273
|
yield sock
|
@@ -263,8 +276,4 @@ module DEBUGGER__
|
|
263
276
|
end
|
264
277
|
end
|
265
278
|
end
|
266
|
-
|
267
|
-
def self.message msg
|
268
|
-
$stderr.puts "DEBUGGER: #{msg}"
|
269
|
-
end
|
270
279
|
end
|
data/lib/debug/server_dap.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module DEBUGGER__
|
@@ -5,7 +7,7 @@ module DEBUGGER__
|
|
5
7
|
SHOW_PROTOCOL = ENV['RUBY_DEBUG_DAP_SHOW_PROTOCOL'] == '1'
|
6
8
|
|
7
9
|
def dap_setup bytes
|
8
|
-
DEBUGGER__.set_config(
|
10
|
+
DEBUGGER__.set_config(no_color: true)
|
9
11
|
@seq = 0
|
10
12
|
|
11
13
|
$stderr.puts '[>]' + bytes if SHOW_PROTOCOL
|
@@ -436,7 +438,7 @@ module DEBUGGER__
|
|
436
438
|
when :backtrace
|
437
439
|
event! :dap_result, :backtrace, req, {
|
438
440
|
stackFrames: @target_frames.map.with_index{|frame, i|
|
439
|
-
path = frame.
|
441
|
+
path = frame.realpath
|
440
442
|
ref = frame.file_lines unless File.exist?(path)
|
441
443
|
|
442
444
|
{
|
data/lib/debug/session.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# skip to load debugger for bundle exec
|
3
4
|
return if $0.end_with?('bin/bundle') && ARGV.first == 'exec'
|
4
5
|
|
@@ -52,6 +53,8 @@ class RubyVM::InstructionSequence
|
|
52
53
|
end
|
53
54
|
|
54
55
|
module DEBUGGER__
|
56
|
+
PresetCommand = Struct.new(:commands, :source, :auto_continue)
|
57
|
+
|
55
58
|
class Session
|
56
59
|
def initialize ui
|
57
60
|
@ui = ui
|
@@ -67,7 +70,7 @@ module DEBUGGER__
|
|
67
70
|
@displays = []
|
68
71
|
@tc = nil
|
69
72
|
@tc_id = 0
|
70
|
-
@
|
73
|
+
@preset_command = nil
|
71
74
|
|
72
75
|
@frame_map = {} # {id => [threadId, frame_depth]} for DAP
|
73
76
|
@var_map = {1 => [:globals], } # {id => ...} for DAP
|
@@ -98,6 +101,12 @@ module DEBUGGER__
|
|
98
101
|
@tp_thread_begin.enable
|
99
102
|
end
|
100
103
|
|
104
|
+
def reset_ui ui
|
105
|
+
@ui.close
|
106
|
+
@ui = ui
|
107
|
+
@management_threads << @ui.reader_thread if @ui.respond_to? :reader_thread
|
108
|
+
end
|
109
|
+
|
101
110
|
def session_server_main
|
102
111
|
while evt = @q_evt.pop
|
103
112
|
# varible `@internal_info` is only used for test
|
@@ -105,6 +114,8 @@ module DEBUGGER__
|
|
105
114
|
output.each{|str| @ui.puts str}
|
106
115
|
|
107
116
|
case ev
|
117
|
+
when :init
|
118
|
+
wait_command_loop tc
|
108
119
|
when :load
|
109
120
|
iseq, src = ev_args
|
110
121
|
on_load iseq, src
|
@@ -133,10 +144,6 @@ module DEBUGGER__
|
|
133
144
|
end
|
134
145
|
when :result
|
135
146
|
case ev_args.first
|
136
|
-
when :watch
|
137
|
-
bp = ev_args[1]
|
138
|
-
@bps[bp.key] = bp
|
139
|
-
show_bps bp
|
140
147
|
when :try_display
|
141
148
|
failed_results = ev_args[1]
|
142
149
|
if failed_results.size > 0
|
@@ -145,10 +152,10 @@ module DEBUGGER__
|
|
145
152
|
@ui.puts "canceled: #{@displays.pop}"
|
146
153
|
end
|
147
154
|
end
|
148
|
-
when :method_breakpoint
|
155
|
+
when :method_breakpoint, :watch_breakpoint
|
149
156
|
bp = ev_args[1]
|
150
157
|
if bp
|
151
|
-
|
158
|
+
add_breakpoint(bp)
|
152
159
|
show_bps bp
|
153
160
|
else
|
154
161
|
# can't make a bp
|
@@ -169,15 +176,24 @@ module DEBUGGER__
|
|
169
176
|
@th_clients.each{|th, thc| thc.close}
|
170
177
|
end
|
171
178
|
|
172
|
-
def
|
173
|
-
cmds.
|
174
|
-
c.gsub(
|
175
|
-
|
176
|
-
}
|
179
|
+
def add_preset_commands name, cmds, kick: true, continue: true
|
180
|
+
cs = cmds.map{|c|
|
181
|
+
c = c.strip.gsub(/\A\s*\#.*/, '').strip
|
182
|
+
c unless c.empty?
|
183
|
+
}.compact
|
184
|
+
|
185
|
+
unless cs.empty?
|
186
|
+
if @preset_command
|
187
|
+
@preset_command.commands += cs
|
188
|
+
else
|
189
|
+
@preset_command = PresetCommand.new(cs, name, continue)
|
190
|
+
end
|
191
|
+
ThreadClient.current.on_init name if kick
|
192
|
+
end
|
177
193
|
end
|
178
194
|
|
179
195
|
def source iseq
|
180
|
-
if CONFIG[:
|
196
|
+
if !CONFIG[:no_color]
|
181
197
|
@sr.get_colored(iseq)
|
182
198
|
else
|
183
199
|
@sr.get(iseq)
|
@@ -207,12 +223,23 @@ module DEBUGGER__
|
|
207
223
|
end
|
208
224
|
|
209
225
|
def wait_command
|
210
|
-
if @
|
226
|
+
if @preset_command
|
227
|
+
if @preset_command.commands.empty?
|
228
|
+
if @preset_command.auto_continue
|
229
|
+
@preset_command = nil
|
230
|
+
@tc << :continue
|
231
|
+
return
|
232
|
+
else
|
233
|
+
@preset_command = nil
|
234
|
+
return :retry
|
235
|
+
end
|
236
|
+
else
|
237
|
+
line = @preset_command.commands.shift
|
238
|
+
@ui.puts "(rdbg:#{@preset_command.source}) #{line}"
|
239
|
+
end
|
240
|
+
else
|
211
241
|
@ui.puts "INTERNAL_INFO: #{JSON.generate(@internal_info)}" if ENV['RUBY_DEBUG_TEST_MODE']
|
212
242
|
line = @ui.readline
|
213
|
-
else
|
214
|
-
line = @initial_commands.shift.strip
|
215
|
-
@ui.puts "(rdbg:init) #{line}"
|
216
243
|
end
|
217
244
|
|
218
245
|
case line
|
@@ -247,21 +274,25 @@ module DEBUGGER__
|
|
247
274
|
# * `s[tep]`
|
248
275
|
# * Step in. Resume the program until next breakable point.
|
249
276
|
when 's', 'step'
|
277
|
+
cancel_auto_continue
|
250
278
|
@tc << [:step, :in]
|
251
279
|
|
252
280
|
# * `n[ext]`
|
253
281
|
# * Step over. Resume the program until next line.
|
254
282
|
when 'n', 'next'
|
283
|
+
cancel_auto_continue
|
255
284
|
@tc << [:step, :next]
|
256
285
|
|
257
286
|
# * `fin[ish]`
|
258
287
|
# * Finish this frame. Resume the program until the current frame is finished.
|
259
288
|
when 'fin', 'finish'
|
289
|
+
cancel_auto_continue
|
260
290
|
@tc << [:step, :finish]
|
261
291
|
|
262
292
|
# * `c[ontinue]`
|
263
293
|
# * Resume the program.
|
264
294
|
when 'c', 'continue'
|
295
|
+
cancel_auto_continue
|
265
296
|
@tc << :continue
|
266
297
|
|
267
298
|
# * `q[uit]` or `Ctrl-D`
|
@@ -366,8 +397,8 @@ module DEBUGGER__
|
|
366
397
|
# * Stop the execution when the result of current scope's `@ivar` is changed.
|
367
398
|
# * Note that this feature is super slow.
|
368
399
|
when 'wat', 'watch'
|
369
|
-
if arg
|
370
|
-
@tc << [:
|
400
|
+
if arg && arg.match?(/\A@\w+/)
|
401
|
+
@tc << [:breakpoint, :watch, arg]
|
371
402
|
else
|
372
403
|
show_bps
|
373
404
|
return :retry
|
@@ -481,9 +512,7 @@ module DEBUGGER__
|
|
481
512
|
case arg
|
482
513
|
when /(\d+)/
|
483
514
|
if @displays[n = $1.to_i]
|
484
|
-
|
485
|
-
@displays.delete_at n
|
486
|
-
end
|
515
|
+
@displays.delete_at n
|
487
516
|
end
|
488
517
|
@tc << [:eval, :display, @displays]
|
489
518
|
when nil
|
@@ -560,6 +589,9 @@ module DEBUGGER__
|
|
560
589
|
end
|
561
590
|
@tc << [:eval, :call, 'binding.irb']
|
562
591
|
|
592
|
+
# don't repeat irb command
|
593
|
+
@repl_prev_line = nil
|
594
|
+
|
563
595
|
### Thread control
|
564
596
|
|
565
597
|
# * `th[read]`
|
@@ -608,6 +640,12 @@ module DEBUGGER__
|
|
608
640
|
return :retry
|
609
641
|
end
|
610
642
|
|
643
|
+
def cancel_auto_continue
|
644
|
+
if @preset_command&.auto_continue
|
645
|
+
@preset_command.auto_continue = false
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
611
649
|
def show_help arg
|
612
650
|
DEBUGGER__.helps.each{|cat, cs|
|
613
651
|
cs.each{|ws, desc|
|
@@ -883,10 +921,16 @@ module DEBUGGER__
|
|
883
921
|
|
884
922
|
def add_breakpoint bp
|
885
923
|
if @bps.has_key? bp.key
|
886
|
-
|
924
|
+
unless bp.duplicable?
|
925
|
+
@ui.puts "duplicated breakpoint: #{bp}"
|
926
|
+
bp.disable
|
927
|
+
end
|
887
928
|
else
|
888
929
|
@bps[bp.key] = bp
|
889
930
|
end
|
931
|
+
|
932
|
+
# don't repeat commands that add breakpoints
|
933
|
+
@repl_prev_line = nil
|
890
934
|
end
|
891
935
|
|
892
936
|
def rehash_bps
|
@@ -932,6 +976,7 @@ module DEBUGGER__
|
|
932
976
|
def add_line_breakpoint file, line, **kw
|
933
977
|
file = resolve_path(file)
|
934
978
|
bp = LineBreakpoint.new(file, line, **kw)
|
979
|
+
|
935
980
|
add_breakpoint bp
|
936
981
|
rescue Errno::ENOENT => e
|
937
982
|
@ui.puts e.message
|
@@ -1022,44 +1067,71 @@ module DEBUGGER__
|
|
1022
1067
|
|
1023
1068
|
# start methods
|
1024
1069
|
|
1025
|
-
def self.
|
1070
|
+
def self.start nonstop: false, **kw
|
1026
1071
|
set_config(kw)
|
1027
1072
|
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1073
|
+
unless defined? SESSION
|
1074
|
+
require_relative 'console'
|
1075
|
+
initialize_session UI_Console.new
|
1076
|
+
end
|
1031
1077
|
|
1032
|
-
|
1033
|
-
ThreadClient.current.on_trap :SIGINT
|
1034
|
-
}
|
1078
|
+
setup_initial_suspend unless nonstop
|
1035
1079
|
end
|
1036
1080
|
|
1037
|
-
def self.open host: nil, port: ::DEBUGGER__::CONFIG[:port], sock_path: nil, sock_dir: nil, **kw
|
1081
|
+
def self.open host: nil, port: ::DEBUGGER__::CONFIG[:port], sock_path: nil, sock_dir: nil, nonstop: false, **kw
|
1038
1082
|
set_config(kw)
|
1039
1083
|
|
1040
1084
|
if port
|
1041
|
-
open_tcp host: host, port: port
|
1085
|
+
open_tcp host: host, port: port, nonstop: nonstop
|
1042
1086
|
else
|
1043
|
-
open_unix sock_path: sock_path, sock_dir: sock_dir
|
1087
|
+
open_unix sock_path: sock_path, sock_dir: sock_dir, nonstop: nonstop
|
1044
1088
|
end
|
1045
1089
|
end
|
1046
1090
|
|
1047
|
-
def self.open_tcp host: nil, port:, **kw
|
1091
|
+
def self.open_tcp host: nil, port:, nonstop: false, **kw
|
1048
1092
|
set_config(kw)
|
1049
1093
|
require_relative 'server'
|
1050
|
-
|
1094
|
+
|
1095
|
+
if defined? SESSION
|
1096
|
+
SESSION.reset_ui UI_TcpServer.new(host: host, port: port)
|
1097
|
+
else
|
1098
|
+
initialize_session UI_TcpServer.new(host: host, port: port)
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
setup_initial_suspend unless nonstop
|
1051
1102
|
end
|
1052
1103
|
|
1053
|
-
def self.open_unix sock_path: nil, sock_dir: nil, **kw
|
1104
|
+
def self.open_unix sock_path: nil, sock_dir: nil, nonstop: false, **kw
|
1054
1105
|
set_config(kw)
|
1055
1106
|
require_relative 'server'
|
1056
|
-
|
1107
|
+
|
1108
|
+
if defined? SESSION
|
1109
|
+
SESSION.reset_ui UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path)
|
1110
|
+
else
|
1111
|
+
initialize_session UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path)
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
setup_initial_suspend unless nonstop
|
1057
1115
|
end
|
1058
1116
|
|
1059
1117
|
# boot utilities
|
1060
1118
|
|
1119
|
+
def self.setup_initial_suspend
|
1120
|
+
if !::DEBUGGER__::CONFIG[:nonstop]
|
1121
|
+
if loc = ::DEBUGGER__.require_location
|
1122
|
+
# require 'debug/console' or 'debug'
|
1123
|
+
add_line_breakpoint loc.absolute_path, loc.lineno + 1, oneshot: true, hook_call: false
|
1124
|
+
else
|
1125
|
+
# -r
|
1126
|
+
add_line_breakpoint $0, 1, oneshot: true, hook_call: false
|
1127
|
+
end
|
1128
|
+
end
|
1129
|
+
end
|
1130
|
+
|
1061
1131
|
class << self
|
1062
1132
|
define_method :initialize_session do |ui|
|
1133
|
+
DEBUGGER__.warn "Session start (pid: #{Process.pid})"
|
1134
|
+
|
1063
1135
|
::DEBUGGER__.const_set(:SESSION, Session.new(ui))
|
1064
1136
|
|
1065
1137
|
# default breakpoints
|
@@ -1067,10 +1139,15 @@ module DEBUGGER__
|
|
1067
1139
|
# ::DEBUGGER__.add_catch_breakpoint 'RuntimeError'
|
1068
1140
|
|
1069
1141
|
Binding.module_eval do
|
1070
|
-
def bp command: nil
|
1142
|
+
def bp command: nil, nonstop: nil
|
1071
1143
|
if command
|
1072
1144
|
cmds = command.split(";;")
|
1073
|
-
|
1145
|
+
# nonstop
|
1146
|
+
# nil, true -> auto_continue
|
1147
|
+
# false -> stop
|
1148
|
+
SESSION.add_preset_commands 'binding.bp(command:)', cmds,
|
1149
|
+
kick: false,
|
1150
|
+
continue: nonstop == false ? false : true
|
1074
1151
|
end
|
1075
1152
|
|
1076
1153
|
::DEBUGGER__.add_line_breakpoint __FILE__, __LINE__ + 1, oneshot: true
|
@@ -1078,36 +1155,26 @@ module DEBUGGER__
|
|
1078
1155
|
end
|
1079
1156
|
end
|
1080
1157
|
|
1081
|
-
if !::DEBUGGER__::CONFIG[:nonstop]
|
1082
|
-
if loc = ::DEBUGGER__.require_location
|
1083
|
-
# require 'debug/console' or 'debug'
|
1084
|
-
add_line_breakpoint loc.absolute_path, loc.lineno + 1, oneshot: true, hook_call: false
|
1085
|
-
else
|
1086
|
-
# -r
|
1087
|
-
add_line_breakpoint $0, 1, oneshot: true, hook_call: false
|
1088
|
-
end
|
1089
|
-
end
|
1090
|
-
|
1091
1158
|
load_rc
|
1092
1159
|
end
|
1093
1160
|
end
|
1094
1161
|
|
1095
1162
|
def self.load_rc
|
1096
|
-
[
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
[init_script = ::DEBUGGER__::CONFIG[:init_script],
|
1104
|
-
'./.rdbgrc',
|
1105
|
-
File.expand_path('~/.rdbgrc')].each{|path|
|
1106
|
-
next unless path
|
1163
|
+
[[File.expand_path('~/.rdbgrc'), true],
|
1164
|
+
[File.expand_path('~/.rdbgrc.rb'), true],
|
1165
|
+
# ['./.rdbgrc', true], # disable because of security concern
|
1166
|
+
[::DEBUGGER__::CONFIG[:init_script], false],
|
1167
|
+
].each{|(path, rc)|
|
1168
|
+
next unless path
|
1169
|
+
next if rc && ::DEBUGGER__::CONFIG[:no_rc] # ignore rc
|
1107
1170
|
|
1108
1171
|
if File.file? path
|
1109
|
-
|
1110
|
-
|
1172
|
+
if path.end_with?('.rb')
|
1173
|
+
load path
|
1174
|
+
else
|
1175
|
+
::DEBUGGER__::SESSION.add_preset_commands path, File.readlines(path)
|
1176
|
+
end
|
1177
|
+
elsif !rc
|
1111
1178
|
warn "Not found: #{path}"
|
1112
1179
|
end
|
1113
1180
|
}
|
@@ -1115,7 +1182,7 @@ module DEBUGGER__
|
|
1115
1182
|
# given debug commands
|
1116
1183
|
if ::DEBUGGER__::CONFIG[:commands]
|
1117
1184
|
cmds = ::DEBUGGER__::CONFIG[:commands].split(';;')
|
1118
|
-
::DEBUGGER__::SESSION.
|
1185
|
+
::DEBUGGER__::SESSION.add_preset_commands "commands", cmds, kick: false, continue: false
|
1119
1186
|
end
|
1120
1187
|
end
|
1121
1188
|
|
@@ -1194,4 +1261,13 @@ module DEBUGGER__
|
|
1194
1261
|
str
|
1195
1262
|
end
|
1196
1263
|
end
|
1264
|
+
|
1265
|
+
def self.warn msg, level = :warn
|
1266
|
+
case level
|
1267
|
+
when :warn
|
1268
|
+
STDERR.puts "DEBUGGER: #{msg}" unless CONFIG[:quiet]
|
1269
|
+
when :error
|
1270
|
+
STDERR.puts "DEBUGGER: #{msg}"
|
1271
|
+
end
|
1272
|
+
end
|
1197
1273
|
end
|