readapt 1.0.0 → 1.1.0

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -15
  3. data/.rspec +2 -2
  4. data/.travis.yml +18 -18
  5. data/CHANGELOG.md +72 -69
  6. data/Gemfile +4 -4
  7. data/LICENSE.txt +21 -21
  8. data/README.md +37 -29
  9. data/Rakefile +14 -14
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/exe/readapt +5 -5
  13. data/ext/readapt/breakpoints.c +83 -83
  14. data/ext/readapt/breakpoints.h +11 -11
  15. data/ext/readapt/extconf.rb +0 -0
  16. data/ext/readapt/frame.c +137 -137
  17. data/ext/readapt/frame.h +17 -17
  18. data/ext/readapt/hash_table.c +211 -211
  19. data/ext/readapt/hash_table.h +30 -30
  20. data/ext/readapt/inspector.c +51 -51
  21. data/ext/readapt/inspector.h +8 -8
  22. data/ext/readapt/monitor.c +1 -1
  23. data/ext/readapt/monitor.h +0 -0
  24. data/ext/readapt/normalize.c +59 -59
  25. data/ext/readapt/normalize.h +7 -7
  26. data/ext/readapt/readapt.c +18 -18
  27. data/ext/readapt/stack.c +86 -86
  28. data/ext/readapt/stack.h +20 -20
  29. data/ext/readapt/threads.c +15 -11
  30. data/ext/readapt/threads.h +1 -1
  31. data/lib/readapt.rb +21 -20
  32. data/lib/readapt/adapter.rb +98 -98
  33. data/lib/readapt/breakpoint.rb +20 -20
  34. data/lib/readapt/data_reader.rb +62 -62
  35. data/lib/readapt/debugger.rb +220 -220
  36. data/lib/readapt/error.rb +63 -63
  37. data/lib/readapt/finder.rb +20 -20
  38. data/lib/readapt/frame.rb +40 -40
  39. data/lib/readapt/input.rb +7 -7
  40. data/lib/readapt/message.rb +62 -62
  41. data/lib/readapt/message/attach.rb +11 -11
  42. data/lib/readapt/message/base.rb +32 -32
  43. data/lib/readapt/message/configuration_done.rb +11 -11
  44. data/lib/readapt/message/continue.rb +15 -15
  45. data/lib/readapt/message/disconnect.rb +13 -13
  46. data/lib/readapt/message/evaluate.rb +18 -18
  47. data/lib/readapt/message/initialize.rb +13 -13
  48. data/lib/readapt/message/launch.rb +11 -11
  49. data/lib/readapt/message/next.rb +12 -12
  50. data/lib/readapt/message/pause.rb +11 -11
  51. data/lib/readapt/message/scopes.rb +26 -26
  52. data/lib/readapt/message/set_breakpoints.rb +25 -25
  53. data/lib/readapt/message/set_exception_breakpoints.rb +8 -8
  54. data/lib/readapt/message/stack_trace.rb +38 -38
  55. data/lib/readapt/message/step_in.rb +11 -11
  56. data/lib/readapt/message/step_out.rb +11 -11
  57. data/lib/readapt/message/threads.rb +18 -18
  58. data/lib/readapt/message/variables.rb +61 -61
  59. data/lib/readapt/monitor.rb +0 -0
  60. data/lib/readapt/output.rb +25 -25
  61. data/lib/readapt/references.rb +27 -0
  62. data/lib/readapt/server.rb +22 -22
  63. data/lib/readapt/shell.rb +104 -104
  64. data/lib/readapt/snapshot.rb +0 -0
  65. data/lib/readapt/thread.rb +23 -23
  66. data/lib/readapt/variable.rb +1 -1
  67. data/lib/readapt/version.rb +3 -3
  68. data/readapt.gemspec +39 -39
  69. metadata +4 -3
@@ -1,220 +1,220 @@
1
- # frozen_string_literal: true
2
-
3
- require 'backport'
4
- require 'observer'
5
- require 'set'
6
-
7
- module Readapt
8
- class Debugger
9
- include Observable
10
- include Finder
11
-
12
- attr_reader :monitor
13
-
14
- attr_reader :file
15
-
16
- def initialize
17
- @stack = []
18
- @frames = {}
19
- @running = false
20
- @attached = false
21
- @request = nil
22
- @config = {}
23
- @original_argv = ARGV.clone
24
- @original_prog = $0
25
- @breakpoints = {}
26
- end
27
-
28
- def config arguments, request
29
- @file = Readapt.normalize_path(find(arguments['program']))
30
- @config = arguments
31
- @request = request
32
- rescue LoadError => e
33
- STDERR.puts e.message
34
- end
35
-
36
- # @return [Readapt::Thread]
37
- def thread id
38
- Thread.find(id)
39
- end
40
-
41
- def threads
42
- Thread.all
43
- end
44
-
45
- def frame id
46
- @frames[id] || Frame::NULL_FRAME
47
- end
48
-
49
- def launched?
50
- @request == :launch
51
- end
52
-
53
- def attached?
54
- @request == :attach
55
- end
56
-
57
- def start
58
- ::Thread.new do
59
- set_program_args
60
- run { load @file }
61
- set_original_args
62
- end
63
- end
64
-
65
- def run
66
- # raise RuntimeError, 'Debugger is already running' if @running
67
- @running = true
68
- send_event('process', {
69
- name: @file
70
- })
71
- Monitor.start @file do |snapshot|
72
- debug snapshot
73
- end
74
- yield if block_given?
75
- rescue StandardError => e
76
- STDERR.puts "[#{e.class}] #{e.message}"
77
- STDERR.puts e.backtrace.join("\n")
78
- ensure
79
- Monitor.stop
80
- @running = false
81
- STDOUT.flush #unless STDOUT.closed?
82
- STDERR.flush #unless STDERR.closed?
83
- changed
84
- send_event 'terminated', nil
85
- end
86
-
87
- def output data, category = :console
88
- send_event('output', {
89
- output: data,
90
- category: category
91
- })
92
- end
93
-
94
- def get_breakpoint source, line
95
- @breakpoints["#{source}:#{line}"] || Breakpoint.new(source, line, nil, 0)
96
- end
97
-
98
- def set_breakpoint source, line, condition, hitcount
99
- @breakpoints["#{source}:#{line}"] = Breakpoint.new(source, line, condition, hitcount)
100
- end
101
-
102
- def clear_breakpoints source
103
- @breakpoints.delete_if { |_key, value|
104
- value.source == source
105
- }
106
- end
107
-
108
- def disconnect
109
- shutdown if launched?
110
- @request = nil
111
- end
112
-
113
- def self.run &block
114
- new.run &block
115
- end
116
-
117
- private
118
-
119
- # @param [Snapshot]
120
- # return [void]
121
- def debug snapshot
122
- sleep 0.001 # @todo Trying to let thread data sync
123
- if snapshot.event == :thread_begin || snapshot.event == :entry
124
- thr = Thread.find(snapshot.thread_id)
125
- thr.control = :continue
126
- send_event('thread', {
127
- reason: 'started',
128
- threadId: snapshot.thread_id
129
- }, true)
130
- snapshot.control = :continue
131
- elsif snapshot.event == :thread_end
132
- thr = thread(snapshot.thread_id)
133
- thr.control = :continue
134
- # @threads.delete snapshot.thread_id
135
- send_event('thread', {
136
- reason: 'exited',
137
- threadId: snapshot.thread_id
138
- })
139
- snapshot.control = :continue
140
- else
141
- confirmed_pause = true
142
- thread = self.thread(snapshot.thread_id)
143
- if snapshot.event == :breakpoint
144
- bp = get_breakpoint(snapshot.file, snapshot.line)
145
- unless bp.condition.nil? || bp.condition.empty?
146
- # @type [Binding]
147
- bnd = thread.frames.first.frame_binding
148
- begin
149
- unless bnd.eval(bp.condition)
150
- confirmed_pause = false
151
- end
152
- rescue Exception => e
153
- STDERR.puts "Breakpoint condition raised an error"
154
- STDERR.puts "#{snapshot.file}:#{snapshot.line} - `#{bp.condition}`"
155
- STDERR.puts "[#{e.class}] #{e.message}"
156
- confirmed_pause = false
157
- end
158
- end
159
- unless !confirmed_pause || bp.hit_condition.nil? || bp.hit_condition.empty?
160
- bp.hit_cursor += 1
161
- bnd = thread.frames.first.frame_binding
162
- begin
163
- hit_count = bnd.eval(bp.hit_condition)
164
- if bp.hit_cursor == hit_count
165
- bp.hit_cursor = 0
166
- else
167
- confirmed_pause = false
168
- end
169
- rescue Exception => e
170
- STDERR.puts "Breakpoint condition raised an error"
171
- STDERR.puts "#{snapshot.file}:#{snapshot.line} - `#{bp.condition}`"
172
- STDERR.puts "[#{e.class}] #{e.message}"
173
- confirmed_pause = false
174
- end
175
- end
176
- end
177
- if confirmed_pause
178
- changed
179
- thread.control = :pause
180
- thread.frames.each do |frm|
181
- @frames[frm.local_id] = frm
182
- end
183
- send_event('stopped', {
184
- reason: snapshot.event,
185
- threadId: thread.id
186
- })
187
- sleep 0.01 until thread.control != :pause || !Thread.include?(thread.id)
188
- thread.frames.each do |frm|
189
- @frames.delete frm.local_id
190
- end
191
- else
192
- thread.control = :continue
193
- end
194
- snapshot.control = thread.control
195
- end
196
- end
197
-
198
- def set_program_args
199
- $0 = file
200
- ARGV.clear
201
- ARGV.replace(@config['programArgs'] || [])
202
- end
203
-
204
- def set_original_args
205
- $0 = @original_prog
206
- ARGV.clear
207
- ARGV.replace @original_argv
208
- end
209
-
210
- def shutdown
211
- exit
212
- end
213
-
214
- def send_event event, data, wait = false
215
- changed
216
- notify_observers event, data
217
- sleep 0.01 if wait
218
- end
219
- end
220
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'backport'
4
+ require 'observer'
5
+ require 'set'
6
+
7
+ module Readapt
8
+ class Debugger
9
+ include Observable
10
+ include Finder
11
+
12
+ attr_reader :monitor
13
+
14
+ attr_reader :file
15
+
16
+ def initialize
17
+ @stack = []
18
+ @frames = {}
19
+ @running = false
20
+ @attached = false
21
+ @request = nil
22
+ @config = {}
23
+ @original_argv = ARGV.clone
24
+ @original_prog = $0
25
+ @breakpoints = {}
26
+ end
27
+
28
+ def config arguments, request
29
+ @file = Readapt.normalize_path(find(arguments['program']))
30
+ @config = arguments
31
+ @request = request
32
+ rescue LoadError => e
33
+ STDERR.puts e.message
34
+ end
35
+
36
+ # @return [Readapt::Thread]
37
+ def thread id
38
+ Thread.find(id)
39
+ end
40
+
41
+ def threads
42
+ Thread.all
43
+ end
44
+
45
+ def frame id
46
+ @frames[id] || Frame::NULL_FRAME
47
+ end
48
+
49
+ def launched?
50
+ @request == :launch
51
+ end
52
+
53
+ def attached?
54
+ @request == :attach
55
+ end
56
+
57
+ def start
58
+ ::Thread.new do
59
+ set_program_args
60
+ run { load @file }
61
+ set_original_args
62
+ end
63
+ end
64
+
65
+ def run
66
+ # raise RuntimeError, 'Debugger is already running' if @running
67
+ @running = true
68
+ send_event('process', {
69
+ name: @file
70
+ })
71
+ Monitor.start @file do |snapshot|
72
+ debug snapshot
73
+ end
74
+ yield if block_given?
75
+ rescue StandardError => e
76
+ STDERR.puts "[#{e.class}] #{e.message}"
77
+ STDERR.puts e.backtrace.join("\n")
78
+ ensure
79
+ Monitor.stop
80
+ @running = false
81
+ STDOUT.flush #unless STDOUT.closed?
82
+ STDERR.flush #unless STDERR.closed?
83
+ changed
84
+ send_event 'terminated', nil
85
+ end
86
+
87
+ def output data, category = :console
88
+ send_event('output', {
89
+ output: data,
90
+ category: category
91
+ })
92
+ end
93
+
94
+ def get_breakpoint source, line
95
+ @breakpoints["#{source}:#{line}"] || Breakpoint.new(source, line, nil, 0)
96
+ end
97
+
98
+ def set_breakpoint source, line, condition, hitcount
99
+ @breakpoints["#{source}:#{line}"] = Breakpoint.new(source, line, condition, hitcount)
100
+ end
101
+
102
+ def clear_breakpoints source
103
+ @breakpoints.delete_if { |_key, value|
104
+ value.source == source
105
+ }
106
+ end
107
+
108
+ def disconnect
109
+ shutdown if launched?
110
+ @request = nil
111
+ end
112
+
113
+ def self.run &block
114
+ new.run &block
115
+ end
116
+
117
+ private
118
+
119
+ # @param [Snapshot]
120
+ # return [void]
121
+ def debug snapshot
122
+ sleep 0.001 # @todo Trying to let thread data sync
123
+ References.clear
124
+ if snapshot.event == :thread_begin || snapshot.event == :entry
125
+ thr = Thread.find(snapshot.thread_id)
126
+ thr.control = :continue
127
+ send_event('thread', {
128
+ reason: 'started',
129
+ threadId: snapshot.thread_id
130
+ }, true)
131
+ snapshot.control = :continue
132
+ elsif snapshot.event == :thread_end
133
+ thr = thread(snapshot.thread_id)
134
+ thr.control = :continue
135
+ send_event('thread', {
136
+ reason: 'exited',
137
+ threadId: snapshot.thread_id
138
+ })
139
+ snapshot.control = :continue
140
+ else
141
+ confirmed_pause = true
142
+ thread = self.thread(snapshot.thread_id)
143
+ if snapshot.event == :breakpoint
144
+ bp = get_breakpoint(snapshot.file, snapshot.line)
145
+ unless bp.condition.nil? || bp.condition.empty?
146
+ # @type [Binding]
147
+ bnd = thread.frames.first.frame_binding
148
+ begin
149
+ unless bnd.eval(bp.condition)
150
+ confirmed_pause = false
151
+ end
152
+ rescue Exception => e
153
+ STDERR.puts "Breakpoint condition raised an error"
154
+ STDERR.puts "#{snapshot.file}:#{snapshot.line} - `#{bp.condition}`"
155
+ STDERR.puts "[#{e.class}] #{e.message}"
156
+ confirmed_pause = false
157
+ end
158
+ end
159
+ unless !confirmed_pause || bp.hit_condition.nil? || bp.hit_condition.empty?
160
+ bp.hit_cursor += 1
161
+ bnd = thread.frames.first.frame_binding
162
+ begin
163
+ hit_count = bnd.eval(bp.hit_condition)
164
+ if bp.hit_cursor == hit_count
165
+ bp.hit_cursor = 0
166
+ else
167
+ confirmed_pause = false
168
+ end
169
+ rescue Exception => e
170
+ STDERR.puts "Breakpoint condition raised an error"
171
+ STDERR.puts "#{snapshot.file}:#{snapshot.line} - `#{bp.condition}`"
172
+ STDERR.puts "[#{e.class}] #{e.message}"
173
+ confirmed_pause = false
174
+ end
175
+ end
176
+ end
177
+ if confirmed_pause
178
+ changed
179
+ thread.control = :pause
180
+ thread.frames.each do |frm|
181
+ @frames[frm.local_id] = frm
182
+ end
183
+ send_event('stopped', {
184
+ reason: snapshot.event,
185
+ threadId: thread.id
186
+ })
187
+ sleep 0.01 until thread.control != :pause || !Thread.include?(thread.id)
188
+ thread.frames.each do |frm|
189
+ @frames.delete frm.local_id
190
+ end
191
+ else
192
+ thread.control = :continue
193
+ end
194
+ snapshot.control = thread.control
195
+ end
196
+ end
197
+
198
+ def set_program_args
199
+ $0 = file
200
+ ARGV.clear
201
+ ARGV.replace(@config['programArgs'] || [])
202
+ end
203
+
204
+ def set_original_args
205
+ $0 = @original_prog
206
+ ARGV.clear
207
+ ARGV.replace @original_argv
208
+ end
209
+
210
+ def shutdown
211
+ exit
212
+ end
213
+
214
+ def send_event event, data, wait = false
215
+ changed
216
+ notify_observers event, data
217
+ sleep 0.01 if wait
218
+ end
219
+ end
220
+ end
@@ -1,63 +1,63 @@
1
- require 'securerandom'
2
-
3
- module Readapt
4
- module Error
5
- class << self
6
- attr_accessor :adapter
7
- end
8
-
9
- def opening
10
- @buffer = ''
11
- end
12
-
13
- def receiving data
14
- output = ''
15
- data.each_char do |char|
16
- @buffer += char
17
- if open_message.start_with?(@buffer) || @buffer.start_with?(open_message)
18
- if @buffer.end_with?(close_message)
19
- msg = @buffer[open_message.length..-(close_message.length+1)]
20
- exit if msg == '__TERMINATE__'
21
- Error.adapter.write msg
22
- @buffer.clear
23
- end
24
- else
25
- output += @buffer
26
- @buffer.clear
27
- end
28
- end
29
- return if output.empty?
30
- send_event('output', {
31
- output: output,
32
- category: 'stderr'
33
- })
34
- end
35
-
36
- def send_event event, data
37
- obj = {
38
- type: 'event',
39
- event: event
40
- }
41
- obj[:body] = data unless data.nil?
42
- json = obj.to_json
43
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
44
- Error.adapter.write envelope
45
- end
46
-
47
- def self.procid= pid
48
- @@procid = pid
49
- end
50
-
51
- def procid
52
- @@procid
53
- end
54
-
55
- def open_message
56
- @@open_message ||= "<readapt-#{procid}>"
57
- end
58
-
59
- def close_message
60
- @@close_message ||= "</readapt-#{procid}>"
61
- end
62
- end
63
- end
1
+ require 'securerandom'
2
+
3
+ module Readapt
4
+ module Error
5
+ class << self
6
+ attr_accessor :adapter
7
+ end
8
+
9
+ def opening
10
+ @buffer = ''
11
+ end
12
+
13
+ def receiving data
14
+ output = ''
15
+ data.each_char do |char|
16
+ @buffer += char
17
+ if open_message.start_with?(@buffer) || @buffer.start_with?(open_message)
18
+ if @buffer.end_with?(close_message)
19
+ msg = @buffer[open_message.length..-(close_message.length+1)]
20
+ exit if msg == '__TERMINATE__'
21
+ Error.adapter.write msg
22
+ @buffer.clear
23
+ end
24
+ else
25
+ output += @buffer
26
+ @buffer.clear
27
+ end
28
+ end
29
+ return if output.empty?
30
+ send_event('output', {
31
+ output: output,
32
+ category: 'stderr'
33
+ })
34
+ end
35
+
36
+ def send_event event, data
37
+ obj = {
38
+ type: 'event',
39
+ event: event
40
+ }
41
+ obj[:body] = data unless data.nil?
42
+ json = obj.to_json
43
+ envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
44
+ Error.adapter.write envelope
45
+ end
46
+
47
+ def self.procid= pid
48
+ @@procid = pid
49
+ end
50
+
51
+ def procid
52
+ @@procid
53
+ end
54
+
55
+ def open_message
56
+ @@open_message ||= "<readapt-#{procid}>"
57
+ end
58
+
59
+ def close_message
60
+ @@close_message ||= "</readapt-#{procid}>"
61
+ end
62
+ end
63
+ end