readapt 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|