debug 1.6.2 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +20 -8
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +39 -16
- data/Rakefile +0 -0
- data/TODO.md +8 -8
- data/debug.gemspec +1 -1
- data/exe/rdbg +17 -2
- data/ext/debug/debug.c +15 -1
- data/ext/debug/extconf.rb +0 -0
- data/ext/debug/iseq_collector.c +0 -0
- data/lib/debug/abbrev_command.rb +77 -0
- data/lib/debug/breakpoint.rb +17 -11
- data/lib/debug/client.rb +27 -10
- data/lib/debug/color.rb +0 -0
- data/lib/debug/config.rb +34 -16
- data/lib/debug/console.rb +0 -0
- data/lib/debug/frame_info.rb +0 -0
- data/lib/debug/local.rb +16 -10
- data/lib/debug/open.rb +0 -0
- data/lib/debug/open_nonstop.rb +0 -0
- data/lib/debug/prelude.rb +1 -1
- data/lib/debug/server.rb +25 -21
- data/lib/debug/server_cdp.rb +293 -87
- data/lib/debug/server_dap.rb +133 -48
- data/lib/debug/session.rb +390 -208
- data/lib/debug/source_repository.rb +39 -19
- data/lib/debug/start.rb +1 -1
- data/lib/debug/thread_client.rb +197 -64
- data/lib/debug/tracer.rb +0 -0
- data/lib/debug/version.rb +1 -1
- data/lib/debug.rb +7 -3
- data/misc/README.md.erb +11 -5
- metadata +5 -4
data/lib/debug/config.rb
CHANGED
@@ -14,6 +14,7 @@ module DEBUGGER__
|
|
14
14
|
# UI setting
|
15
15
|
log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger", :loglevel, "WARN"],
|
16
16
|
show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint", :int, "10"],
|
17
|
+
show_evaledsrc: ['RUBY_DEBUG_SHOW_EVALEDSRC', "UI: Show actually evaluated source", :bool, "false"],
|
17
18
|
show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint", :int, "2"],
|
18
19
|
use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool, "false"],
|
19
20
|
no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize", :bool, "false"],
|
@@ -33,12 +34,13 @@ module DEBUGGER__
|
|
33
34
|
nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool, "false"],
|
34
35
|
stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool, "false"],
|
35
36
|
init_script: ['RUBY_DEBUG_INIT_SCRIPT', "BOOT: debug command script path loaded at first stop"],
|
36
|
-
commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop.
|
37
|
+
commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop. Commands should be separated by `;;`"],
|
37
38
|
no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool, "false"],
|
38
39
|
history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file", :string, "~/.rdbg_history"],
|
39
40
|
save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines", :int, "10000"],
|
40
41
|
|
41
42
|
# remote setting
|
43
|
+
open: ['RUBY_DEBUG_OPEN', "REMOTE: Open remote port (same as `rdbg --open` option)"],
|
42
44
|
port: ['RUBY_DEBUG_PORT', "REMOTE: TCP/IP remote debugging: port"],
|
43
45
|
host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"],
|
44
46
|
sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"],
|
@@ -46,7 +48,6 @@ module DEBUGGER__
|
|
46
48
|
local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map],
|
47
49
|
skip_bp: ['RUBY_DEBUG_SKIP_BP', "REMOTE: Skip breakpoints if no clients are attached", :bool, 'false'],
|
48
50
|
cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"],
|
49
|
-
open_frontend: ['RUBY_DEBUG_OPEN_FRONTEND',"REMOTE: frontend used by open command (vscode, chrome, default: rdbg)."],
|
50
51
|
chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"],
|
51
52
|
|
52
53
|
# obsolete
|
@@ -63,8 +64,6 @@ module DEBUGGER__
|
|
63
64
|
end
|
64
65
|
|
65
66
|
def initialize argv
|
66
|
-
@skip_all = false
|
67
|
-
|
68
67
|
if self.class.config
|
69
68
|
raise 'Can not make multiple configurations in one process'
|
70
69
|
end
|
@@ -94,14 +93,6 @@ module DEBUGGER__
|
|
94
93
|
set_config(key => val)
|
95
94
|
end
|
96
95
|
|
97
|
-
def skip_all
|
98
|
-
@skip_all = true
|
99
|
-
end
|
100
|
-
|
101
|
-
def skip?
|
102
|
-
@skip_all
|
103
|
-
end
|
104
|
-
|
105
96
|
def set_config(**kw)
|
106
97
|
conf = config.dup
|
107
98
|
kw.each{|k, v|
|
@@ -158,6 +149,12 @@ module DEBUGGER__
|
|
158
149
|
if_updated old_conf, conf, :sigdump_sig do |old_sig, new_sig|
|
159
150
|
setup_sigdump old_sig, new_sig
|
160
151
|
end
|
152
|
+
|
153
|
+
if_updated old_conf, conf, :no_sigint_hook do |old, new|
|
154
|
+
if defined?(SESSION)
|
155
|
+
SESSION.set_no_sigint_hook old, new
|
156
|
+
end
|
157
|
+
end
|
161
158
|
end
|
162
159
|
|
163
160
|
private def if_updated old_conf, new_conf, key
|
@@ -308,8 +305,25 @@ module DEBUGGER__
|
|
308
305
|
'If TCP/IP options are not given, a UNIX domain socket will be used.',
|
309
306
|
'If FRONTEND is given, prepare for the FRONTEND.',
|
310
307
|
'Now rdbg, vscode and chrome is supported.') do |f|
|
311
|
-
|
312
|
-
|
308
|
+
|
309
|
+
case f # some format patterns are not documented yet
|
310
|
+
when nil
|
311
|
+
config[:open] = true
|
312
|
+
when /\A\d\z/
|
313
|
+
config[:open] = true
|
314
|
+
config[:port] = f.to_i
|
315
|
+
when /\A(\S+):(\d+)\z/
|
316
|
+
config[:open] = true
|
317
|
+
config[:host] = $1
|
318
|
+
config[:port] = $2.to_i
|
319
|
+
when 'tcp'
|
320
|
+
config[:open] = true
|
321
|
+
config[:port] ||= 0
|
322
|
+
when 'vscode', 'chrome', 'cdp'
|
323
|
+
config[:open] = f&.downcase
|
324
|
+
else
|
325
|
+
raise "Unknown option for --open: #{f}"
|
326
|
+
end
|
313
327
|
end
|
314
328
|
o.on('--sock-path=SOCK_PATH', 'UNIX Domain socket path') do |path|
|
315
329
|
config[:sock_path] = path
|
@@ -479,10 +493,14 @@ module DEBUGGER__
|
|
479
493
|
when /\A\s*### (.+)/
|
480
494
|
cat = $1
|
481
495
|
break if $1 == 'END'
|
482
|
-
when /\A
|
496
|
+
when /\A register_command (.+)/
|
483
497
|
next unless cat
|
484
498
|
next unless desc
|
485
|
-
|
499
|
+
|
500
|
+
ws = []
|
501
|
+
$1.gsub(/'([a-z]+)'/){|w|
|
502
|
+
ws << $1
|
503
|
+
}
|
486
504
|
helps[cat] << [ws, desc]
|
487
505
|
desc = nil
|
488
506
|
max_w = ws.max_by{|w| w.length}
|
data/lib/debug/console.rb
CHANGED
File without changes
|
data/lib/debug/frame_info.rb
CHANGED
File without changes
|
data/lib/debug/local.rb
CHANGED
@@ -13,23 +13,28 @@ module DEBUGGER__
|
|
13
13
|
false
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
session.intercept_trap_sigint_start prev_handler
|
24
|
-
end
|
16
|
+
def activate_sigint
|
17
|
+
prev_handler = trap(:SIGINT){
|
18
|
+
if SESSION.active?
|
19
|
+
ThreadClient.current.on_trap :SIGINT
|
20
|
+
end
|
21
|
+
}
|
22
|
+
SESSION.intercept_trap_sigint_start prev_handler
|
25
23
|
end
|
26
24
|
|
27
|
-
def
|
25
|
+
def deactivate_sigint
|
28
26
|
if SESSION.intercept_trap_sigint?
|
29
27
|
prev = SESSION.intercept_trap_sigint_end
|
30
28
|
trap(:SIGINT, prev)
|
31
29
|
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def activate session, on_fork: false
|
33
|
+
activate_sigint unless CONFIG[:no_sigint_hook]
|
34
|
+
end
|
32
35
|
|
36
|
+
def deactivate
|
37
|
+
deactivate_sigint
|
33
38
|
@console.deactivate
|
34
39
|
end
|
35
40
|
|
@@ -42,6 +47,7 @@ module DEBUGGER__
|
|
42
47
|
end
|
43
48
|
|
44
49
|
def quit n
|
50
|
+
yield
|
45
51
|
exit n
|
46
52
|
end
|
47
53
|
|
data/lib/debug/open.rb
CHANGED
File without changes
|
data/lib/debug/open_nonstop.rb
CHANGED
File without changes
|
data/lib/debug/prelude.rb
CHANGED
data/lib/debug/server.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'socket'
|
4
|
-
require 'etc'
|
5
4
|
require_relative 'config'
|
6
5
|
require_relative 'version'
|
7
6
|
|
@@ -22,6 +21,7 @@ module DEBUGGER__
|
|
22
21
|
|
23
22
|
class Terminate < StandardError; end
|
24
23
|
class GreetingError < StandardError; end
|
24
|
+
class RetryConnection < StandardError; end
|
25
25
|
|
26
26
|
def deactivate
|
27
27
|
@reader_thread.raise Terminate
|
@@ -78,6 +78,8 @@ module DEBUGGER__
|
|
78
78
|
next
|
79
79
|
rescue Terminate
|
80
80
|
raise # should catch at outer scope
|
81
|
+
rescue RetryConnection
|
82
|
+
next
|
81
83
|
rescue => e
|
82
84
|
DEBUGGER__.warn "ReaderThreadError: #{e}"
|
83
85
|
pp e.backtrace
|
@@ -128,6 +130,8 @@ module DEBUGGER__
|
|
128
130
|
def greeting
|
129
131
|
case g = @sock.gets
|
130
132
|
when /^info cookie:\s+(.*)$/
|
133
|
+
require 'etc'
|
134
|
+
|
131
135
|
check_cookie $1
|
132
136
|
@sock.puts "PID: #{Process.pid}, $0: #{$0}"
|
133
137
|
@sock.puts "debug #{VERSION} on #{RUBY_DESCRIPTION}"
|
@@ -140,7 +144,8 @@ module DEBUGGER__
|
|
140
144
|
|
141
145
|
# TODO: protocol version
|
142
146
|
if v != VERSION
|
143
|
-
|
147
|
+
@sock.puts msg = "out DEBUGGER: Incompatible version (server:#{VERSION} and client:#{$1})"
|
148
|
+
raise GreetingError, msg
|
144
149
|
end
|
145
150
|
parse_option(params)
|
146
151
|
|
@@ -157,16 +162,13 @@ module DEBUGGER__
|
|
157
162
|
@need_pause_at_first = false
|
158
163
|
dap_setup @sock.read($1.to_i)
|
159
164
|
|
160
|
-
when /^GET
|
165
|
+
when /^GET\s\/json\sHTTP\/1.1/, /^GET\s\/json\/version\sHTTP\/1.1/, /^GET\s\/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\sHTTP\/1.1/
|
166
|
+
# The reason for not using @uuid here is @uuid is nil if users run debugger without `--open=chrome`.
|
167
|
+
|
161
168
|
require_relative 'server_cdp'
|
162
169
|
|
163
170
|
self.extend(UI_CDP)
|
164
|
-
|
165
|
-
@need_pause_at_first = false
|
166
|
-
CONFIG.set_config no_color: true
|
167
|
-
|
168
|
-
@ws_server = UI_CDP::WebSocketServer.new(@sock)
|
169
|
-
@ws_server.handshake
|
171
|
+
send_chrome_response g
|
170
172
|
else
|
171
173
|
raise GreetingError, "Unknown greeting message: #{g}"
|
172
174
|
end
|
@@ -174,17 +176,17 @@ module DEBUGGER__
|
|
174
176
|
|
175
177
|
def process
|
176
178
|
while true
|
177
|
-
DEBUGGER__.
|
178
|
-
|
179
|
-
DEBUGGER__.
|
179
|
+
DEBUGGER__.debug{ "sleep IO.select" }
|
180
|
+
_r = IO.select([@sock])
|
181
|
+
DEBUGGER__.debug{ "wakeup IO.select" }
|
180
182
|
|
181
183
|
line = @session.process_group.sync do
|
182
184
|
unless IO.select([@sock], nil, nil, 0)
|
183
|
-
DEBUGGER__.
|
185
|
+
DEBUGGER__.debug{ "UI_Server can not read" }
|
184
186
|
break :can_not_read
|
185
187
|
end
|
186
188
|
@sock.gets&.chomp.tap{|line|
|
187
|
-
DEBUGGER__.
|
189
|
+
DEBUGGER__.debug{ "UI_Server received: #{line}" }
|
188
190
|
}
|
189
191
|
end
|
190
192
|
|
@@ -340,12 +342,12 @@ module DEBUGGER__
|
|
340
342
|
if @repl
|
341
343
|
raise "not in subsession, but received: #{line.inspect}" unless @session.in_subsession?
|
342
344
|
line = "input #{Process.pid}"
|
343
|
-
DEBUGGER__.
|
345
|
+
DEBUGGER__.debug{ "send: #{line}" }
|
344
346
|
s.puts line
|
345
347
|
end
|
346
348
|
sleep 0.01 until @q_msg
|
347
349
|
@q_msg.pop.tap{|msg|
|
348
|
-
DEBUGGER__.
|
350
|
+
DEBUGGER__.debug{ "readline: #{msg.inspect}" }
|
349
351
|
}
|
350
352
|
end || 'continue')
|
351
353
|
|
@@ -361,7 +363,7 @@ module DEBUGGER__
|
|
361
363
|
Process.kill(TRAP_SIGNAL, Process.pid)
|
362
364
|
end
|
363
365
|
|
364
|
-
def quit n
|
366
|
+
def quit n, &_b
|
365
367
|
# ignore n
|
366
368
|
sock do |s|
|
367
369
|
s.puts "quit"
|
@@ -395,6 +397,7 @@ module DEBUGGER__
|
|
395
397
|
raise "Specify digits for port number"
|
396
398
|
end
|
397
399
|
end
|
400
|
+
@uuid = nil # for CDP
|
398
401
|
|
399
402
|
super()
|
400
403
|
end
|
@@ -402,11 +405,12 @@ module DEBUGGER__
|
|
402
405
|
def chrome_setup
|
403
406
|
require_relative 'server_cdp'
|
404
407
|
|
405
|
-
|
408
|
+
@uuid = SecureRandom.uuid
|
409
|
+
unless @chrome_pid = UI_CDP.setup_chrome(@local_addr.inspect_sockaddr, @uuid)
|
406
410
|
DEBUGGER__.warn <<~EOS
|
407
411
|
With Chrome browser, type the following URL in the address-bar:
|
408
412
|
|
409
|
-
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=#{@local_addr.inspect_sockaddr}/#{
|
413
|
+
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=#{@local_addr.inspect_sockaddr}/#{@uuid}
|
410
414
|
|
411
415
|
EOS
|
412
416
|
end
|
@@ -434,7 +438,7 @@ module DEBUGGER__
|
|
434
438
|
#
|
435
439
|
EOS
|
436
440
|
|
437
|
-
case CONFIG[:
|
441
|
+
case CONFIG[:open]
|
438
442
|
when 'chrome'
|
439
443
|
chrome_setup
|
440
444
|
when 'vscode'
|
@@ -491,7 +495,7 @@ module DEBUGGER__
|
|
491
495
|
end
|
492
496
|
|
493
497
|
::DEBUGGER__.warn "Debugger can attach via UNIX domain socket (#{@sock_path})"
|
494
|
-
vscode_setup @sock_path if CONFIG[:
|
498
|
+
vscode_setup @sock_path if CONFIG[:open] == 'vscode'
|
495
499
|
|
496
500
|
begin
|
497
501
|
Socket.unix_server_loop @sock_path do |sock, client|
|