debug 1.0.0.beta5 → 1.0.0.rc1
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/CONTRIBUTING.md +213 -20
- data/Gemfile +1 -0
- data/README.md +460 -226
- data/Rakefile +2 -1
- data/TODO.md +0 -6
- data/bin/gentest +22 -0
- data/debug.gemspec +1 -0
- data/exe/rdbg +11 -18
- data/ext/debug/debug.c +11 -1
- data/lib/debug/breakpoint.rb +106 -62
- data/lib/debug/client.rb +11 -17
- data/lib/debug/color.rb +28 -7
- data/lib/debug/config.rb +378 -144
- data/lib/debug/console.rb +79 -57
- data/lib/debug/frame_info.rb +42 -8
- data/lib/debug/local.rb +91 -0
- data/lib/debug/open.rb +2 -1
- data/lib/debug/open_nonstop.rb +15 -0
- data/lib/debug/server.rb +96 -43
- data/lib/debug/server_dap.rb +34 -7
- data/lib/debug/session.rb +827 -341
- data/lib/debug/source_repository.rb +2 -0
- data/lib/debug/start.rb +5 -0
- data/lib/debug/thread_client.rb +691 -184
- data/lib/debug/tracer.rb +242 -0
- data/lib/debug/version.rb +3 -1
- data/lib/debug.rb +3 -0
- data/misc/README.md.erb +341 -216
- metadata +21 -4
- data/lib/debug/run.rb +0 -4
- data/lib/debug/test_console.rb +0 -0
data/lib/debug/console.rb
CHANGED
@@ -1,49 +1,87 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module DEBUGGER__
|
3
|
+
class Console
|
4
|
+
begin
|
5
|
+
raise LoadError if CONFIG[:no_reline]
|
6
|
+
require 'reline'
|
3
7
|
|
4
|
-
|
8
|
+
# reline 0.2.7 or later is required.
|
9
|
+
raise LoadError if Reline::VERSION < '0.2.6'
|
5
10
|
|
6
|
-
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
end
|
11
|
+
require_relative 'color'
|
12
|
+
include Color
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
# 0.2.7 has SIGWINCH issue on non-main thread
|
15
|
+
class ::Reline::LineEditor
|
16
|
+
m = Module.new do
|
17
|
+
def reset(prompt = '', encoding:)
|
18
|
+
super
|
19
|
+
Signal.trap(:SIGWINCH, nil)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
prepend m
|
23
|
+
end
|
14
24
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
25
|
+
def readline_setup prompt
|
26
|
+
commands = DEBUGGER__.commands
|
18
27
|
|
19
|
-
|
20
|
-
|
21
|
-
|
28
|
+
Reline.completion_proc = -> given do
|
29
|
+
buff = Reline.line_buffer
|
30
|
+
Reline.completion_append_character= ' '
|
22
31
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
32
|
+
if /\s/ =~ buff # second parameters
|
33
|
+
given = File.expand_path(given + 'a').sub(/a\z/, '')
|
34
|
+
files = Dir.glob(given + '*')
|
35
|
+
if files.size == 1 && File.directory?(files.first)
|
36
|
+
Reline.completion_append_character= '/'
|
37
|
+
end
|
38
|
+
files
|
39
|
+
else
|
40
|
+
commands.keys.grep(/\A#{given}/)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Reline.output_modifier_proc = -> buff, **kw do
|
45
|
+
c, rest = get_command buff
|
46
|
+
|
47
|
+
case
|
48
|
+
when commands.keys.include?(c = c.strip)
|
49
|
+
# [:DIM, :CYAN, :BLUE, :CLEAR, :UNDERLINE, :REVERSE, :RED, :GREEN, :MAGENTA, :BOLD, :YELLOW]
|
50
|
+
cmd = colorize(c.strip, [:CYAN, :UNDERLINE])
|
51
|
+
|
52
|
+
if commands[c] == c
|
53
|
+
rprompt = colorize(" # command", [:DIM])
|
54
|
+
else
|
55
|
+
rprompt = colorize(" # #{commands[c]} command", [:DIM])
|
56
|
+
end
|
57
|
+
|
58
|
+
rest = (rest ? colorize_code(rest) : '') + rprompt
|
59
|
+
cmd + rest
|
60
|
+
when !rest && /\A\s*[a-z]*\z/ =~ c
|
61
|
+
buff
|
62
|
+
else
|
63
|
+
colorize_code(buff.chomp) + colorize(" # ruby", [:DIM])
|
64
|
+
end
|
65
|
+
end
|
27
66
|
end
|
28
|
-
end
|
29
67
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
68
|
+
private def get_command line
|
69
|
+
case line.chomp
|
70
|
+
when /\A(\s*[a-z]+)(\s.*)?\z$/
|
71
|
+
return $1, $2
|
72
|
+
else
|
73
|
+
line.chomp
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def readline prompt
|
78
|
+
readline_setup prompt
|
79
|
+
Reline.readmultiline(prompt, true){ true }
|
42
80
|
end
|
43
|
-
end
|
44
81
|
|
82
|
+
rescue LoadError
|
45
83
|
begin
|
46
|
-
require 'readline'
|
84
|
+
require 'readline.so'
|
47
85
|
|
48
86
|
def readline_setup
|
49
87
|
Readline.completion_proc = proc{|given|
|
@@ -58,38 +96,22 @@ module DEBUGGER__
|
|
58
96
|
end
|
59
97
|
files
|
60
98
|
else
|
61
|
-
DEBUGGER__.commands.grep(/\A#{given}/)
|
99
|
+
DEBUGGER__.commands.keys.grep(/\A#{given}/)
|
62
100
|
end
|
63
101
|
}
|
64
102
|
end
|
65
103
|
|
66
|
-
def
|
104
|
+
def readline prompt
|
67
105
|
readline_setup
|
68
|
-
Readline.readline(
|
106
|
+
Readline.readline(prompt, true)
|
69
107
|
end
|
108
|
+
|
70
109
|
rescue LoadError
|
71
|
-
def
|
72
|
-
print
|
110
|
+
def readline prompt
|
111
|
+
print prompt
|
73
112
|
gets
|
74
113
|
end
|
75
114
|
end
|
76
|
-
|
77
|
-
def readline
|
78
|
-
setup_interrupt do
|
79
|
-
(readline_body || 'quit').strip
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def setup_interrupt
|
84
|
-
current_thread = Thread.current # should be session_server thread
|
85
|
-
|
86
|
-
prev_handler = trap(:INT){
|
87
|
-
current_thread.raise Interrupt
|
88
|
-
}
|
89
|
-
|
90
|
-
yield
|
91
|
-
ensure
|
92
|
-
trap(:INT, prev_handler)
|
93
115
|
end
|
94
116
|
end
|
95
117
|
end
|
data/lib/debug/frame_info.rb
CHANGED
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module DEBUGGER__
|
3
4
|
FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :frame_depth,
|
4
5
|
:has_return_value, :return_value,
|
5
6
|
:has_raised_exception, :raised_exception,
|
6
|
-
:show_line
|
7
|
+
:show_line,
|
8
|
+
:_local_variables, :_callee # for recorder
|
9
|
+
)
|
7
10
|
|
8
11
|
# extend FrameInfo with debug.so
|
9
12
|
if File.exist? File.join(__dir__, 'debug.so')
|
10
13
|
require_relative 'debug.so'
|
11
14
|
else
|
12
|
-
|
15
|
+
require_relative 'debug'
|
13
16
|
end
|
14
17
|
|
15
18
|
class FrameInfo
|
@@ -24,10 +27,10 @@ module DEBUGGER__
|
|
24
27
|
end
|
25
28
|
|
26
29
|
def pretty_path
|
27
|
-
use_short_path =
|
30
|
+
use_short_path = CONFIG[:use_short_path]
|
28
31
|
|
29
32
|
case
|
30
|
-
when use_short_path && path.start_with?(dir =
|
33
|
+
when use_short_path && path.start_with?(dir = CONFIG["rubylibdir"] + '/')
|
31
34
|
path.sub(dir, '$(rubylibdir)/')
|
32
35
|
when use_short_path && Gem.path.any? do |gp|
|
33
36
|
path.start_with?(dir = gp + '/gems/')
|
@@ -61,7 +64,7 @@ module DEBUGGER__
|
|
61
64
|
end
|
62
65
|
|
63
66
|
def frame_type
|
64
|
-
if
|
67
|
+
if self.local_variables && iseq
|
65
68
|
if iseq.type == :block
|
66
69
|
:block
|
67
70
|
elsif callee
|
@@ -101,11 +104,11 @@ module DEBUGGER__
|
|
101
104
|
end
|
102
105
|
|
103
106
|
def callee
|
104
|
-
|
107
|
+
self._callee ||= self.binding&.eval('__callee__')
|
105
108
|
end
|
106
109
|
|
107
110
|
def return_str
|
108
|
-
if binding && iseq && has_return_value
|
111
|
+
if self.binding && iseq && has_return_value
|
109
112
|
DEBUGGER__.short_inspect(return_value)
|
110
113
|
end
|
111
114
|
end
|
@@ -114,6 +117,33 @@ module DEBUGGER__
|
|
114
117
|
"#{pretty_path}:#{location.lineno}"
|
115
118
|
end
|
116
119
|
|
120
|
+
private def make_binding
|
121
|
+
__newb__ = self.self.instance_eval('binding')
|
122
|
+
self.local_variables.each{|var, val|
|
123
|
+
__newb__.local_variable_set(var, val)
|
124
|
+
}
|
125
|
+
__newb__
|
126
|
+
end
|
127
|
+
|
128
|
+
def eval_binding
|
129
|
+
if b = self.binding
|
130
|
+
b
|
131
|
+
elsif self.local_variables
|
132
|
+
make_binding
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def local_variables
|
137
|
+
if lvars = self._local_variables
|
138
|
+
lvars
|
139
|
+
elsif b = self.binding
|
140
|
+
lvars = b.local_variables.map{|var|
|
141
|
+
[var, b.local_variable_get(var)]
|
142
|
+
}.to_h
|
143
|
+
self._local_variables = lvars
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
117
147
|
private
|
118
148
|
|
119
149
|
def get_singleton_class obj
|
@@ -122,11 +152,15 @@ module DEBUGGER__
|
|
122
152
|
nil
|
123
153
|
end
|
124
154
|
|
155
|
+
private def local_variable_get var
|
156
|
+
local_variables[var]
|
157
|
+
end
|
158
|
+
|
125
159
|
def parameters_info(argc)
|
126
160
|
vars = iseq.locals[0...argc]
|
127
161
|
vars.map{|var|
|
128
162
|
begin
|
129
|
-
{ name: var, value: DEBUGGER__.short_inspect(
|
163
|
+
{ name: var, value: DEBUGGER__.short_inspect(local_variable_get(var)) }
|
130
164
|
rescue NameError, TypeError
|
131
165
|
nil
|
132
166
|
end
|
data/lib/debug/local.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'io/console/size'
|
4
|
+
require_relative 'console'
|
5
|
+
|
6
|
+
module DEBUGGER__
|
7
|
+
class UI_LocalConsole < UI_Base
|
8
|
+
def initialize
|
9
|
+
@console = Console.new
|
10
|
+
|
11
|
+
unless CONFIG[:no_sigint_hook]
|
12
|
+
@prev_handler = trap(:SIGINT){
|
13
|
+
if SESSION.active?
|
14
|
+
ThreadClient.current.on_trap :SIGINT
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
if @prev_handler
|
22
|
+
trap(:SIGINT, @prev_handler)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def remote?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
def activate on_fork: false
|
31
|
+
# Do nothing
|
32
|
+
end
|
33
|
+
|
34
|
+
def deactivate
|
35
|
+
# Do nothing
|
36
|
+
end
|
37
|
+
|
38
|
+
def width
|
39
|
+
if (w = IO.console_size[1]) == 0 # for tests PTY
|
40
|
+
80
|
41
|
+
else
|
42
|
+
w
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def quit n
|
47
|
+
exit n
|
48
|
+
end
|
49
|
+
|
50
|
+
def ask prompt
|
51
|
+
setup_interrupt do
|
52
|
+
print prompt
|
53
|
+
($stdin.gets || '').strip
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def puts str = nil
|
58
|
+
case str
|
59
|
+
when Array
|
60
|
+
str.each{|line|
|
61
|
+
$stdout.puts line.chomp
|
62
|
+
}
|
63
|
+
when String
|
64
|
+
str.each_line{|line|
|
65
|
+
$stdout.puts line.chomp
|
66
|
+
}
|
67
|
+
when nil
|
68
|
+
$stdout.puts
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def readline prompt = '(rdbg)'
|
73
|
+
setup_interrupt do
|
74
|
+
(@console.readline(prompt) || 'quit').strip
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup_interrupt
|
79
|
+
current_thread = Thread.current # should be session_server thread
|
80
|
+
|
81
|
+
prev_handler = trap(:INT){
|
82
|
+
current_thread.raise Interrupt
|
83
|
+
}
|
84
|
+
|
85
|
+
yield
|
86
|
+
ensure
|
87
|
+
trap(:INT, prev_handler)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
data/lib/debug/open.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
#
|
2
3
|
# Open the door for the debugger to connect.
|
3
4
|
# Users can connect to debuggee program with "rdbg --attach" option.
|
@@ -6,7 +7,7 @@
|
|
6
7
|
# Otherwise, UNIX domain socket is used.
|
7
8
|
#
|
8
9
|
|
9
|
-
require_relative '
|
10
|
+
require_relative 'session'
|
10
11
|
return unless defined?(DEBUGGER__)
|
11
12
|
|
12
13
|
DEBUGGER__.open
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Open the door for the debugger to connect.
|
4
|
+
# Unlike debug/open, it does not stop at the beginning of the program.
|
5
|
+
# Users can connect to debuggee program with "rdbg --attach" option or
|
6
|
+
# VSCode attach type.
|
7
|
+
#
|
8
|
+
# If RUBY_DEBUG_PORT envval is provided (digits), open TCP/IP port.
|
9
|
+
# Otherwise, UNIX domain socket is used.
|
10
|
+
#
|
11
|
+
|
12
|
+
require_relative 'session'
|
13
|
+
return unless defined?(DEBUGGER__)
|
14
|
+
|
15
|
+
DEBUGGER__.open(nonstop: true)
|
data/lib/debug/server.rb
CHANGED
@@ -1,29 +1,49 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative 'session'
|
4
|
-
return unless defined?(DEBUGGER__)
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
3
|
+
require 'socket'
|
6
4
|
require_relative 'config'
|
7
5
|
require_relative 'version'
|
8
6
|
|
9
7
|
module DEBUGGER__
|
10
8
|
class UI_ServerBase < UI_Base
|
11
9
|
def initialize
|
12
|
-
@sock = nil
|
10
|
+
@sock = @sock_for_fork = nil
|
13
11
|
@accept_m = Mutex.new
|
14
12
|
@accept_cv = ConditionVariable.new
|
15
13
|
@client_addr = nil
|
16
|
-
@q_msg =
|
17
|
-
@q_ans =
|
14
|
+
@q_msg = nil
|
15
|
+
@q_ans = nil
|
18
16
|
@unsent_messages = []
|
19
17
|
@width = 80
|
20
18
|
|
19
|
+
activate
|
20
|
+
end
|
21
|
+
|
22
|
+
class Terminate < StandardError
|
23
|
+
end
|
24
|
+
|
25
|
+
def deactivate
|
26
|
+
@reader_thread.raise Terminate
|
27
|
+
end
|
28
|
+
|
29
|
+
def accept
|
30
|
+
if @sock_for_fork
|
31
|
+
begin
|
32
|
+
yield @sock_for_fork, already_connected: true
|
33
|
+
ensure
|
34
|
+
@sock_for_fork.close
|
35
|
+
@sock_for_fork = nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def activate on_fork: false
|
21
41
|
@reader_thread = Thread.new do
|
22
42
|
# An error on this thread should break the system.
|
23
43
|
Thread.current.abort_on_exception = true
|
24
44
|
|
25
|
-
accept do |server|
|
26
|
-
DEBUGGER__.
|
45
|
+
accept do |server, already_connected: false|
|
46
|
+
DEBUGGER__.warn "Connected."
|
27
47
|
|
28
48
|
@accept_m.synchronize{
|
29
49
|
@sock = server
|
@@ -36,20 +56,31 @@ module DEBUGGER__
|
|
36
56
|
@sock.puts m
|
37
57
|
}
|
38
58
|
@unsent_messages.clear
|
39
|
-
|
59
|
+
|
60
|
+
@q_msg = Queue.new
|
61
|
+
@q_ans = Queue.new
|
62
|
+
} unless already_connected
|
40
63
|
|
41
64
|
setup_interrupt do
|
65
|
+
pause unless already_connected
|
42
66
|
process
|
43
67
|
end
|
44
68
|
|
69
|
+
rescue Terminate
|
70
|
+
raise # should catch at outer scope
|
45
71
|
rescue => e
|
46
|
-
DEBUGGER__.
|
72
|
+
DEBUGGER__.warn "ReaderThreadError: #{e}"
|
47
73
|
ensure
|
48
|
-
DEBUGGER__.
|
74
|
+
DEBUGGER__.warn "Disconnected."
|
49
75
|
@sock = nil
|
50
76
|
@q_msg.close
|
77
|
+
@q_msg = nil
|
51
78
|
@q_ans.close
|
52
|
-
|
79
|
+
@q_ans = nil
|
80
|
+
end # accept
|
81
|
+
|
82
|
+
rescue Terminate
|
83
|
+
# ignore
|
53
84
|
end
|
54
85
|
end
|
55
86
|
|
@@ -81,11 +112,6 @@ module DEBUGGER__
|
|
81
112
|
end
|
82
113
|
|
83
114
|
def process
|
84
|
-
@q_msg = Queue.new
|
85
|
-
@q_ans = Queue.new
|
86
|
-
|
87
|
-
pause
|
88
|
-
|
89
115
|
while line = @sock.gets
|
90
116
|
case line
|
91
117
|
when /\Apause/
|
@@ -129,10 +155,6 @@ module DEBUGGER__
|
|
129
155
|
trap(:SIGINT, prev_handler)
|
130
156
|
end
|
131
157
|
|
132
|
-
def accept
|
133
|
-
raise "NOT IMPLEMENTED ERROR"
|
134
|
-
end
|
135
|
-
|
136
158
|
attr_reader :reader_thread
|
137
159
|
|
138
160
|
class NoRemoteError < Exception; end
|
@@ -141,12 +163,20 @@ module DEBUGGER__
|
|
141
163
|
if s = @sock # already connection
|
142
164
|
# ok
|
143
165
|
elsif skip == true # skip process
|
144
|
-
|
166
|
+
no_sock = true
|
167
|
+
r = @accept_m.synchronize do
|
168
|
+
if @sock
|
169
|
+
no_sock = false
|
170
|
+
else
|
171
|
+
yield nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
return r if no_sock
|
145
175
|
else # wait for connection
|
146
176
|
until s = @sock
|
147
177
|
@accept_m.synchronize{
|
148
178
|
unless @sock
|
149
|
-
DEBUGGER__.
|
179
|
+
DEBUGGER__.warn "wait for debugger connection..."
|
150
180
|
@accept_cv.wait(@accept_m)
|
151
181
|
end
|
152
182
|
}
|
@@ -187,11 +217,15 @@ module DEBUGGER__
|
|
187
217
|
end
|
188
218
|
end
|
189
219
|
|
190
|
-
def readline
|
191
|
-
(sock do |s|
|
220
|
+
def readline prompt
|
221
|
+
input = (sock do |s|
|
192
222
|
s.puts "input"
|
223
|
+
sleep 0.01 until @q_msg
|
224
|
+
|
193
225
|
@q_msg.pop
|
194
226
|
end || 'continue').strip
|
227
|
+
|
228
|
+
input
|
195
229
|
end
|
196
230
|
|
197
231
|
def pause
|
@@ -209,9 +243,9 @@ module DEBUGGER__
|
|
209
243
|
|
210
244
|
class UI_TcpServer < UI_ServerBase
|
211
245
|
def initialize host: nil, port: nil
|
212
|
-
@host = host ||
|
246
|
+
@host = host || CONFIG[:host] || '127.0.0.1'
|
213
247
|
@port = port || begin
|
214
|
-
port_str =
|
248
|
+
port_str = CONFIG[:port] || raise("Specify listening port by RUBY_DEBUG_PORT environment variable.")
|
215
249
|
if /\A\d+\z/ !~ port_str
|
216
250
|
raise "Specify digits for port number"
|
217
251
|
else
|
@@ -223,17 +257,34 @@ module DEBUGGER__
|
|
223
257
|
end
|
224
258
|
|
225
259
|
def accept
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
260
|
+
retry_cnt = 0
|
261
|
+
super # for fork
|
262
|
+
|
263
|
+
begin
|
264
|
+
Socket.tcp_server_sockets @host, @port do |socks|
|
265
|
+
::DEBUGGER__.warn "Debugger can attach via TCP/IP (#{socks.map{|e| e.local_address.inspect}})"
|
266
|
+
Socket.accept_loop(socks) do |sock, client|
|
267
|
+
@client_addr = client
|
268
|
+
yield @sock_for_fork = sock
|
269
|
+
end
|
231
270
|
end
|
271
|
+
rescue Errno::EADDRINUSE
|
272
|
+
if retry_cnt < 10
|
273
|
+
retry_cnt += 1
|
274
|
+
sleep 0.1
|
275
|
+
retry
|
276
|
+
else
|
277
|
+
raise
|
278
|
+
end
|
279
|
+
rescue Terminate
|
280
|
+
# OK
|
281
|
+
rescue => e
|
282
|
+
$stderr.puts e.inspect, e.message
|
283
|
+
pp e.backtrace
|
284
|
+
exit
|
232
285
|
end
|
233
|
-
|
234
|
-
|
235
|
-
pp e.backtrace
|
236
|
-
exit
|
286
|
+
ensure
|
287
|
+
@sock_for_fork = nil
|
237
288
|
end
|
238
289
|
end
|
239
290
|
|
@@ -241,30 +292,32 @@ module DEBUGGER__
|
|
241
292
|
def initialize sock_dir: nil, sock_path: nil
|
242
293
|
@sock_path = sock_path
|
243
294
|
@sock_dir = sock_dir || DEBUGGER__.unix_domain_socket_dir
|
295
|
+
@sock_for_fork = nil
|
244
296
|
|
245
297
|
super()
|
246
298
|
end
|
247
299
|
|
248
300
|
def accept
|
301
|
+
super # for fork
|
302
|
+
|
249
303
|
case
|
250
304
|
when @sock_path
|
251
|
-
when sp =
|
305
|
+
when sp = CONFIG[:sock_path]
|
252
306
|
@sock_path = sp
|
253
307
|
else
|
254
308
|
@sock_path = DEBUGGER__.create_unix_domain_socket_name(@sock_dir)
|
255
309
|
end
|
256
310
|
|
257
|
-
::DEBUGGER__.
|
311
|
+
::DEBUGGER__.warn "Debugger can attach via UNIX domain socket (#{@sock_path})"
|
258
312
|
Socket.unix_server_loop @sock_path do |sock, client|
|
313
|
+
@sock_for_fork = sock
|
259
314
|
@client_addr = client
|
315
|
+
|
260
316
|
yield sock
|
261
317
|
ensure
|
262
318
|
sock.close
|
319
|
+
@sock_for_fork = nil
|
263
320
|
end
|
264
321
|
end
|
265
322
|
end
|
266
|
-
|
267
|
-
def self.message msg
|
268
|
-
$stderr.puts "DEBUGGER: #{msg}"
|
269
|
-
end
|
270
323
|
end
|