readapt 0.7.1 → 0.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Rakefile +0 -11
- data/ext/readapt/breakpoints.c +0 -5
- data/ext/readapt/breakpoints.h +0 -1
- data/ext/readapt/frame.c +137 -0
- data/ext/readapt/frame.h +17 -0
- data/ext/readapt/hash_table.c +0 -1
- data/ext/readapt/hash_table.h +0 -2
- data/ext/readapt/inspector.c +51 -0
- data/ext/readapt/inspector.h +8 -0
- data/ext/readapt/monitor.c +39 -26
- data/ext/readapt/normalize.c +14 -8
- data/ext/readapt/normalize.h +1 -1
- data/ext/readapt/readapt.c +2 -0
- data/ext/readapt/stack.c +86 -0
- data/ext/readapt/stack.h +20 -0
- data/ext/readapt/threads.c +105 -15
- data/ext/readapt/threads.h +10 -3
- data/lib/readapt.rb +1 -2
- data/lib/readapt/adapter.rb +3 -3
- data/lib/readapt/breakpoint.rb +8 -1
- data/lib/readapt/debugger.rb +50 -30
- data/lib/readapt/frame.rb +16 -18
- data/lib/readapt/message.rb +10 -7
- data/lib/readapt/message/scopes.rb +2 -1
- data/lib/readapt/message/set_breakpoints.rb +1 -1
- data/lib/readapt/message/stack_trace.rb +16 -4
- data/lib/readapt/message/variables.rb +23 -19
- data/lib/readapt/shell.rb +2 -0
- data/lib/readapt/snapshot.rb +1 -13
- data/lib/readapt/thread.rb +11 -22
- data/lib/readapt/version.rb +1 -1
- metadata +8 -3
- data/lib/readapt/location.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 660628a66dff5d1b46364c85d7ef3f115693463c1a94b18854ca79c7521a5b86
|
4
|
+
data.tar.gz: 4cbbffc522a4907d1819846262c473add5e76404f04bb3c654829301c704e821
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f36dd16bf2e1a396eda01205e80fa5bf0d6ff3a12064297cbd6cba2f2f3643fb527a31c76c659bd4c49c32ae620d7dba72ede08ba677d0187cef0ba9b6b0ec5
|
7
|
+
data.tar.gz: 1e21ac739a23df49966a15a7b99477c5e0e795a8bc9600f779a9cd9c9ff58aa3c11b5a57fb4c9fb9732cf04287fa8614a99ecc561526fc6d20d9b73b4a305690
|
data/CHANGELOG.md
CHANGED
data/Rakefile
CHANGED
@@ -12,14 +12,3 @@ task :default => :spec
|
|
12
12
|
Rake::ExtensionTask.new "readapt" do |ext|
|
13
13
|
ext.lib_dir = "lib/readapt"
|
14
14
|
end
|
15
|
-
|
16
|
-
namespace :install do
|
17
|
-
desc 'Install on Windows'
|
18
|
-
task :win do
|
19
|
-
Dir.mktmpdir do |tmp|
|
20
|
-
gemfile = File.join(tmp, 'readapt.gem')
|
21
|
-
system("gem build readapt.gemspec -o #{gemfile}") &&
|
22
|
-
system("gem install #{gemfile}")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/ext/readapt/breakpoints.c
CHANGED
@@ -54,11 +54,6 @@ int breakpoints_match(char *file, long line)
|
|
54
54
|
return 0;
|
55
55
|
}
|
56
56
|
|
57
|
-
// int breakpoints_match(char *file, long line)
|
58
|
-
// {
|
59
|
-
// return breakpoints_match_id(rb_intern(file), line);
|
60
|
-
// }
|
61
|
-
|
62
57
|
static VALUE breakpoints_match_s(VALUE self, VALUE file, VALUE line)
|
63
58
|
{
|
64
59
|
return breakpoints_match(StringValueCStr(file), NUM2LONG(line)) == 0 ? Qfalse : Qtrue;
|
data/ext/readapt/breakpoints.h
CHANGED
@@ -6,7 +6,6 @@ void initialize_breakpoints(VALUE m_Readapt);
|
|
6
6
|
void breakpoints_set(char *file, long *lines);
|
7
7
|
void breakpoints_delete(char *file);
|
8
8
|
int breakpoints_match(char *file, long line);
|
9
|
-
// int breakpoints_match_id(ht_key file, long line);
|
10
9
|
long breakpoints_files();
|
11
10
|
|
12
11
|
#endif
|
data/ext/readapt/frame.c
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "ruby/debug.h"
|
3
|
+
#include "frame.h"
|
4
|
+
#include "normalize.h"
|
5
|
+
|
6
|
+
static VALUE c_Frame;
|
7
|
+
|
8
|
+
void frame_free(void *data)
|
9
|
+
{
|
10
|
+
frame_t *frm = data;
|
11
|
+
|
12
|
+
free(frm->file);
|
13
|
+
free(frm);
|
14
|
+
}
|
15
|
+
|
16
|
+
static size_t
|
17
|
+
frame_size(const void *data)
|
18
|
+
{
|
19
|
+
return sizeof(frame_t);
|
20
|
+
}
|
21
|
+
|
22
|
+
static const rb_data_type_t frame_type = {
|
23
|
+
.wrap_struct_name = "frame_data",
|
24
|
+
.function = {
|
25
|
+
.dmark = NULL,
|
26
|
+
.dfree = frame_free,
|
27
|
+
.dsize = frame_size,
|
28
|
+
},
|
29
|
+
.data = NULL,
|
30
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
31
|
+
};
|
32
|
+
|
33
|
+
VALUE frame_allocate_s(VALUE self)
|
34
|
+
{
|
35
|
+
VALUE obj;
|
36
|
+
frame_t *data = malloc(sizeof(frame_t));
|
37
|
+
obj = TypedData_Wrap_Struct(self, &frame_type, data);
|
38
|
+
data->file = NULL;
|
39
|
+
data->line = 0;
|
40
|
+
data->binding = Qnil;
|
41
|
+
return obj;
|
42
|
+
}
|
43
|
+
|
44
|
+
VALUE frame_allocate()
|
45
|
+
{
|
46
|
+
return frame_allocate_s(c_Frame);
|
47
|
+
}
|
48
|
+
|
49
|
+
frame_t *frame_data_from_tracepoint(VALUE tracepoint)
|
50
|
+
{
|
51
|
+
frame_t *data;
|
52
|
+
VALUE tmp;
|
53
|
+
rb_trace_arg_t *tracearg;
|
54
|
+
char *file;
|
55
|
+
int line;
|
56
|
+
|
57
|
+
data = malloc(sizeof(frame_t));
|
58
|
+
tracearg = rb_tracearg_from_tracepoint(tracepoint);
|
59
|
+
tmp = rb_tracearg_path(tracearg);
|
60
|
+
file = (tmp == Qnil ? NULL : normalize_path_new_cstr(StringValueCStr(tmp)));
|
61
|
+
line = NUM2INT(rb_tracearg_lineno(tracearg));
|
62
|
+
|
63
|
+
data->file = file;
|
64
|
+
data->line = line;
|
65
|
+
data->binding = Qnil;
|
66
|
+
|
67
|
+
return data;
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE frame_initialize_m(VALUE self, VALUE file, VALUE line, VALUE binding)
|
71
|
+
{
|
72
|
+
frame_t *data;
|
73
|
+
TypedData_Get_Struct(self, frame_t, &frame_type, data);
|
74
|
+
if (file == Qnil)
|
75
|
+
{
|
76
|
+
data->file = NULL;
|
77
|
+
}
|
78
|
+
else
|
79
|
+
{
|
80
|
+
data->file = normalize_path_new_cstr(StringValueCStr(file));
|
81
|
+
}
|
82
|
+
data->line = NUM2INT(line);
|
83
|
+
data->binding = binding;
|
84
|
+
return self;
|
85
|
+
}
|
86
|
+
|
87
|
+
VALUE frame_new_from_data(frame_t *data)
|
88
|
+
{
|
89
|
+
VALUE obj;
|
90
|
+
|
91
|
+
obj = frame_allocate();
|
92
|
+
frame_initialize_m(
|
93
|
+
obj,
|
94
|
+
rb_str_new_cstr(data->file),
|
95
|
+
INT2NUM(data->line),
|
96
|
+
data->binding);
|
97
|
+
|
98
|
+
return obj;
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE frame_file_m(VALUE self)
|
102
|
+
{
|
103
|
+
frame_t *data;
|
104
|
+
VALUE str = Qnil;
|
105
|
+
|
106
|
+
TypedData_Get_Struct(self, frame_t, &frame_type, data);
|
107
|
+
if (data->file)
|
108
|
+
{
|
109
|
+
str = rb_str_new_cstr(data->file);
|
110
|
+
rb_obj_freeze(str);
|
111
|
+
}
|
112
|
+
return str;
|
113
|
+
}
|
114
|
+
|
115
|
+
VALUE frame_line_m(VALUE self)
|
116
|
+
{
|
117
|
+
frame_t *data;
|
118
|
+
TypedData_Get_Struct(self, frame_t, &frame_type, data);
|
119
|
+
return INT2NUM(data->line);
|
120
|
+
}
|
121
|
+
|
122
|
+
VALUE frame_binding_m(VALUE self)
|
123
|
+
{
|
124
|
+
frame_t *data;
|
125
|
+
TypedData_Get_Struct(self, frame_t, &frame_type, data);
|
126
|
+
return data->binding;
|
127
|
+
}
|
128
|
+
|
129
|
+
void initialize_frame(VALUE m_Readapt)
|
130
|
+
{
|
131
|
+
c_Frame = rb_define_class_under(m_Readapt, "Frame", rb_cData);
|
132
|
+
rb_define_alloc_func(c_Frame, frame_allocate_s);
|
133
|
+
rb_define_method(c_Frame, "initialize", frame_initialize_m, 3);
|
134
|
+
rb_define_method(c_Frame, "file", frame_file_m, 0);
|
135
|
+
rb_define_method(c_Frame, "line", frame_line_m, 0);
|
136
|
+
rb_define_method(c_Frame, "frame_binding", frame_binding_m, 0);
|
137
|
+
}
|
data/ext/readapt/frame.h
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef FRAME_H_
|
2
|
+
#define FRAME_H_
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
typedef struct frame_struct {
|
7
|
+
char *file;
|
8
|
+
int line;
|
9
|
+
VALUE binding;
|
10
|
+
} frame_t;
|
11
|
+
|
12
|
+
void initialize_frame(VALUE);
|
13
|
+
frame_t *frame_data_from_tracepoint(VALUE);
|
14
|
+
VALUE frame_new_from_data(frame_t *);
|
15
|
+
void frame_free(void *);
|
16
|
+
|
17
|
+
#endif
|
data/ext/readapt/hash_table.c
CHANGED
data/ext/readapt/hash_table.h
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "ruby/debug.h"
|
3
|
+
#include "frame.h"
|
4
|
+
#include "threads.h"
|
5
|
+
#include "normalize.h"
|
6
|
+
|
7
|
+
static VALUE process_inspection(const rb_debug_inspector_t *inspector, void *ptr)
|
8
|
+
{
|
9
|
+
VALUE locations;
|
10
|
+
long i_size;
|
11
|
+
long i;
|
12
|
+
VALUE loc;
|
13
|
+
VALUE path;
|
14
|
+
int line;
|
15
|
+
VALUE bnd;
|
16
|
+
thread_reference_t *data;
|
17
|
+
frame_t *frm;
|
18
|
+
VALUE iseq;
|
19
|
+
|
20
|
+
data = ptr;
|
21
|
+
|
22
|
+
locations = rb_debug_inspector_backtrace_locations(inspector);
|
23
|
+
i_size = locations == Qnil ? 0 : RARRAY_LENINT(locations);
|
24
|
+
for (i = i_size - 1; i >= 0; i--)
|
25
|
+
{
|
26
|
+
iseq = rb_debug_inspector_frame_iseq_get(inspector, i);
|
27
|
+
if (iseq != Qnil)
|
28
|
+
{
|
29
|
+
loc = rb_ary_entry(locations, i);
|
30
|
+
path = rb_funcall(loc, rb_intern("absolute_path"), 0);
|
31
|
+
line = NUM2INT(rb_funcall(loc, rb_intern("lineno"), 0));
|
32
|
+
bnd = rb_debug_inspector_frame_binding_get(inspector, i);
|
33
|
+
|
34
|
+
frm = malloc(sizeof(frame_t));
|
35
|
+
frm->file = normalize_path_new_cstr(StringValueCStr(path));
|
36
|
+
frm->line = line;
|
37
|
+
frm->binding = bnd;
|
38
|
+
stack_push(data->frames, frm);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
return Qnil;
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Get an array of frames from the Ruby debug inspector.
|
47
|
+
*/
|
48
|
+
void inspector_inspect(thread_reference_t *data)
|
49
|
+
{
|
50
|
+
rb_debug_inspector_open(process_inspection, (void *)data);
|
51
|
+
}
|
data/ext/readapt/monitor.c
CHANGED
@@ -46,18 +46,16 @@ static int match_step(thread_reference_t *ptr)
|
|
46
46
|
static ID
|
47
47
|
monitor_debug(const char *file, const long line, VALUE tracepoint, thread_reference_t *ptr, ID event)
|
48
48
|
{
|
49
|
-
VALUE
|
49
|
+
VALUE snapshot, result, gc_disabled;
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
// Disable garbage collection to avoid segfaults in Frame#frame_binding
|
52
|
+
gc_disabled = rb_gc_disable();
|
53
|
+
thread_reference_build_frames(ptr);
|
54
|
+
snapshot = rb_funcall(c_Snapshot, rb_intern("new"), 4,
|
54
55
|
LONG2NUM(ptr->id),
|
55
|
-
bid,
|
56
56
|
rb_str_new_cstr(file),
|
57
57
|
INT2NUM(line),
|
58
|
-
|
59
|
-
ID2SYM(event),
|
60
|
-
INT2NUM(ptr->depth)
|
58
|
+
ID2SYM(event)
|
61
59
|
);
|
62
60
|
rb_io_flush(rb_stdout);
|
63
61
|
rb_io_flush(rb_stderr);
|
@@ -68,33 +66,44 @@ monitor_debug(const char *file, const long line, VALUE tracepoint, thread_refere
|
|
68
66
|
ptr->cursor = ptr->depth;
|
69
67
|
ptr->control = result;
|
70
68
|
}
|
69
|
+
thread_reference_clear_frames(ptr);
|
70
|
+
if (!RTEST(gc_disabled))
|
71
|
+
{
|
72
|
+
rb_gc_enable();
|
73
|
+
}
|
71
74
|
return result;
|
72
75
|
}
|
73
76
|
|
74
77
|
static void
|
75
78
|
process_line_event(VALUE tracepoint, void *data)
|
76
79
|
{
|
77
|
-
VALUE ref
|
78
|
-
char *tp_file;
|
79
|
-
long tp_line;
|
80
|
+
VALUE ref;
|
80
81
|
thread_reference_t *ptr;
|
81
|
-
rb_trace_arg_t *
|
82
|
+
rb_trace_arg_t *arg;
|
82
83
|
int threadPaused;
|
83
84
|
ID dapEvent;
|
85
|
+
VALUE tmp;
|
86
|
+
char *tp_file;
|
87
|
+
long tp_line;
|
84
88
|
|
85
89
|
ref = thread_current_reference();
|
86
90
|
if (ref != Qnil)
|
87
91
|
{
|
88
92
|
ptr = thread_reference_pointer(ref);
|
89
93
|
threadPaused = (ptr->control == id_pause);
|
94
|
+
|
90
95
|
if (firstLineEvent && ptr->control == id_continue && breakpoints_files() == 0)
|
91
96
|
{
|
92
97
|
return;
|
93
98
|
}
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
99
|
+
|
100
|
+
arg = rb_tracearg_from_tracepoint(tracepoint);
|
101
|
+
tmp = rb_tracearg_path(arg);
|
102
|
+
// tp_file = normalize_path_new_cstr(StringValueCStr(tmp));
|
103
|
+
tp_file = StringValueCStr(tmp);
|
104
|
+
normalize_path(tp_file);
|
105
|
+
tmp = rb_tracearg_lineno(arg);
|
106
|
+
tp_line = NUM2INT(tmp);
|
98
107
|
|
99
108
|
dapEvent = id_continue;
|
100
109
|
if (!firstLineEvent)
|
@@ -128,7 +137,7 @@ process_line_event(VALUE tracepoint, void *data)
|
|
128
137
|
monitor_debug(tp_file, tp_line, tracepoint, ptr, dapEvent);
|
129
138
|
}
|
130
139
|
|
131
|
-
free(tp_file);
|
140
|
+
// free(tp_file);
|
132
141
|
}
|
133
142
|
}
|
134
143
|
|
@@ -163,7 +172,7 @@ process_return_event(VALUE tracepoint, void *data)
|
|
163
172
|
static void
|
164
173
|
process_thread_begin_event(VALUE tracepoint, void *data)
|
165
174
|
{
|
166
|
-
VALUE list, here,
|
175
|
+
VALUE list, here, ref;
|
167
176
|
thread_reference_t *ptr;
|
168
177
|
|
169
178
|
list = rb_funcall(rb_cThread, rb_intern("list"), 0);
|
@@ -189,12 +198,15 @@ process_thread_end_event(VALUE tracepoint, void *data)
|
|
189
198
|
thread_reference_t *ptr;
|
190
199
|
|
191
200
|
thr = rb_thread_current();
|
192
|
-
|
193
|
-
if (ref != Qnil)
|
201
|
+
if (thr != Qnil)
|
194
202
|
{
|
195
|
-
|
196
|
-
|
197
|
-
|
203
|
+
ref = thread_reference(thr);
|
204
|
+
if (ref != Qnil)
|
205
|
+
{
|
206
|
+
ptr = thread_reference_pointer(ref);
|
207
|
+
monitor_debug("", 0, tracepoint, ptr, rb_intern("thread_end"));
|
208
|
+
thread_delete_reference(thr);
|
209
|
+
}
|
198
210
|
}
|
199
211
|
}
|
200
212
|
|
@@ -255,6 +267,7 @@ monitor_disable_s(VALUE self)
|
|
255
267
|
|
256
268
|
free(entryFile);
|
257
269
|
entryFile = NULL;
|
270
|
+
thread_clear();
|
258
271
|
|
259
272
|
return previous;
|
260
273
|
}
|
@@ -280,15 +293,15 @@ void initialize_monitor(VALUE m_Readapt)
|
|
280
293
|
m_Monitor = rb_define_module_under(m_Readapt, "Monitor");
|
281
294
|
c_Snapshot = rb_define_class_under(m_Readapt, "Snapshot", rb_cObject);
|
282
295
|
|
283
|
-
initialize_threads();
|
296
|
+
initialize_threads(m_Readapt);
|
284
297
|
|
285
298
|
rb_define_singleton_method(m_Monitor, "start", monitor_enable_s, 1);
|
286
299
|
rb_define_singleton_method(m_Monitor, "stop", monitor_disable_s, 0);
|
287
300
|
rb_define_singleton_method(m_Monitor, "pause", monitor_pause_s, 1);
|
288
301
|
|
289
302
|
tpLine = rb_tracepoint_new(Qnil, RUBY_EVENT_LINE, process_line_event, NULL);
|
290
|
-
tpCall = rb_tracepoint_new(Qnil, RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS, process_call_event, NULL);
|
291
|
-
tpReturn = rb_tracepoint_new(Qnil, RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END, process_return_event, NULL);
|
303
|
+
tpCall = rb_tracepoint_new(Qnil, RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS | RUBY_EVENT_C_CALL, process_call_event, NULL);
|
304
|
+
tpReturn = rb_tracepoint_new(Qnil, RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END | RUBY_EVENT_C_RETURN, process_return_event, NULL);
|
292
305
|
tpThreadBegin = rb_tracepoint_new(Qnil, RUBY_EVENT_THREAD_BEGIN, process_thread_begin_event, NULL);
|
293
306
|
tpThreadEnd = rb_tracepoint_new(Qnil, RUBY_EVENT_THREAD_END, process_thread_end_event, NULL);
|
294
307
|
debugProc = Qnil;
|
data/ext/readapt/normalize.c
CHANGED
@@ -14,25 +14,31 @@ checkIfWindows()
|
|
14
14
|
return result == Qnil ? 0 : 1;
|
15
15
|
}
|
16
16
|
|
17
|
-
|
17
|
+
void normalize_path(char *str)
|
18
18
|
{
|
19
|
-
char *buffer;
|
20
19
|
long i, len;
|
21
20
|
|
22
|
-
buffer = malloc((strlen(str) + 1) * sizeof(char));
|
23
|
-
strcpy(buffer, str);
|
24
21
|
if (isWindows)
|
25
22
|
{
|
26
|
-
|
27
|
-
len = strlen(
|
23
|
+
str[0] = toupper(str[0]);
|
24
|
+
len = strlen(str);
|
28
25
|
for (i = 2; i < len; i++)
|
29
26
|
{
|
30
|
-
if (
|
27
|
+
if (str[i] == '\\')
|
31
28
|
{
|
32
|
-
|
29
|
+
str[i] = '/';
|
33
30
|
}
|
34
31
|
}
|
35
32
|
}
|
33
|
+
}
|
34
|
+
|
35
|
+
char *normalize_path_new_cstr(char *str)
|
36
|
+
{
|
37
|
+
char *buffer;
|
38
|
+
|
39
|
+
buffer = malloc((strlen(str) + 1) * sizeof(char));
|
40
|
+
strcpy(buffer, str);
|
41
|
+
normalize_path(buffer);
|
36
42
|
return buffer;
|
37
43
|
}
|
38
44
|
|