google-cloud-debugger 0.24.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 +7 -0
- data/.yardopts +8 -0
- data/LICENSE +201 -0
- data/README.md +56 -0
- data/ext/google/cloud/debugger/debugger_c/debugger.c +31 -0
- data/ext/google/cloud/debugger/debugger_c/debugger.h +26 -0
- data/ext/google/cloud/debugger/debugger_c/evaluator.c +78 -0
- data/ext/google/cloud/debugger/debugger_c/evaluator.h +25 -0
- data/ext/google/cloud/debugger/debugger_c/extconf.rb +22 -0
- data/ext/google/cloud/debugger/debugger_c/tracer.c +478 -0
- data/ext/google/cloud/debugger/debugger_c/tracer.h +31 -0
- data/lib/google-cloud-debugger.rb +121 -0
- data/lib/google/cloud/debugger.rb +379 -0
- data/lib/google/cloud/debugger/agent.rb +204 -0
- data/lib/google/cloud/debugger/async_actor.rb +290 -0
- data/lib/google/cloud/debugger/breakpoint.rb +382 -0
- data/lib/google/cloud/debugger/breakpoint/evaluator.rb +1113 -0
- data/lib/google/cloud/debugger/breakpoint/source_location.rb +75 -0
- data/lib/google/cloud/debugger/breakpoint/stack_frame.rb +109 -0
- data/lib/google/cloud/debugger/breakpoint/variable.rb +304 -0
- data/lib/google/cloud/debugger/breakpoint_manager.rb +217 -0
- data/lib/google/cloud/debugger/credentials.rb +41 -0
- data/lib/google/cloud/debugger/debuggee.rb +204 -0
- data/lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb +78 -0
- data/lib/google/cloud/debugger/middleware.rb +77 -0
- data/lib/google/cloud/debugger/project.rb +135 -0
- data/lib/google/cloud/debugger/rails.rb +141 -0
- data/lib/google/cloud/debugger/service.rb +130 -0
- data/lib/google/cloud/debugger/tracer.rb +165 -0
- data/lib/google/cloud/debugger/transmitter.rb +129 -0
- data/lib/google/cloud/debugger/v2.rb +15 -0
- data/lib/google/cloud/debugger/v2/controller2_client.rb +299 -0
- data/lib/google/cloud/debugger/v2/controller2_client_config.json +43 -0
- data/lib/google/cloud/debugger/v2/debugger2_client.rb +378 -0
- data/lib/google/cloud/debugger/v2/debugger2_client_config.json +53 -0
- data/lib/google/cloud/debugger/v2/doc/google/devtools/clouddebugger/v2/data.rb +441 -0
- data/lib/google/cloud/debugger/v2/doc/google/devtools/clouddebugger/v2/debugger.rb +151 -0
- data/lib/google/cloud/debugger/v2/doc/google/devtools/source/v1/source_context.rb +161 -0
- data/lib/google/cloud/debugger/v2/doc/google/protobuf/timestamp.rb +81 -0
- data/lib/google/cloud/debugger/version.rb +22 -0
- data/lib/google/devtools/clouddebugger/v2/controller_pb.rb +47 -0
- data/lib/google/devtools/clouddebugger/v2/controller_services_pb.rb +97 -0
- data/lib/google/devtools/clouddebugger/v2/data_pb.rb +105 -0
- data/lib/google/devtools/clouddebugger/v2/debugger_pb.rb +74 -0
- data/lib/google/devtools/clouddebugger/v2/debugger_services_pb.rb +64 -0
- data/lib/google/devtools/source/v1/source_context_pb.rb +89 -0
- metadata +300 -0
@@ -0,0 +1,478 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2017 Google Inc. All rights reserved.
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
#include "ruby/ruby.h"
|
18
|
+
#include "ruby/debug.h"
|
19
|
+
#include "tracer.h"
|
20
|
+
|
21
|
+
/**
|
22
|
+
* hash_get_keys_callback
|
23
|
+
* Helper callback function for hash_get_keys.
|
24
|
+
*/
|
25
|
+
static int
|
26
|
+
hash_get_keys_callback(VALUE key, VALUE val, VALUE key_ary)
|
27
|
+
{
|
28
|
+
rb_ary_push(key_ary, key);
|
29
|
+
|
30
|
+
return ST_CONTINUE;
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* hash_get_keys
|
35
|
+
* Helper function to return an array of all the keys of a given Ruby array
|
36
|
+
*/
|
37
|
+
static VALUE
|
38
|
+
hash_get_keys(VALUE hash)
|
39
|
+
{
|
40
|
+
VALUE key_ary;
|
41
|
+
|
42
|
+
if(!RB_TYPE_P(hash, T_HASH)) {
|
43
|
+
return Qnil;
|
44
|
+
}
|
45
|
+
|
46
|
+
key_ary = rb_ary_new();
|
47
|
+
|
48
|
+
rb_hash_foreach(hash, hash_get_keys_callback, key_ary);
|
49
|
+
|
50
|
+
return key_ary;
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* match_breakpoints_files
|
55
|
+
* Check the Tracer#breakpoints_cache if any breakpoints match the given
|
56
|
+
* tracepoint_path. Return 1 if found. Otherwise 0;
|
57
|
+
*/
|
58
|
+
static VALUE
|
59
|
+
match_breakpoints_files(VALUE self, VALUE tracepoint_path)
|
60
|
+
{
|
61
|
+
int i;
|
62
|
+
char *c_tracepoint_path = rb_string_value_cstr(&tracepoint_path);
|
63
|
+
|
64
|
+
VALUE path_breakpoints_hash = rb_iv_get(self, "@breakpoints_cache");
|
65
|
+
VALUE breakpoints_paths = hash_get_keys(path_breakpoints_hash);
|
66
|
+
VALUE *c_breakpoints_paths = RARRAY_PTR(breakpoints_paths);
|
67
|
+
int breakpoints_paths_len = RARRAY_LEN(breakpoints_paths);
|
68
|
+
|
69
|
+
for (i = 0; i < breakpoints_paths_len; i++) {
|
70
|
+
VALUE breakpoint_path = c_breakpoints_paths[i];
|
71
|
+
char *c_breakpoint_path = rb_string_value_cstr(&breakpoint_path);
|
72
|
+
|
73
|
+
if (strcmp(c_tracepoint_path, c_breakpoint_path) == 0) {
|
74
|
+
return 1;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
return 0;
|
79
|
+
}
|
80
|
+
|
81
|
+
static VALUE
|
82
|
+
disable_line_trace_for_thread(VALUE thread);
|
83
|
+
|
84
|
+
/**
|
85
|
+
* match_breakpoints
|
86
|
+
* Check the Tracer#breakpoints_cache for any matching breakpoints of given
|
87
|
+
* file path and line number.
|
88
|
+
*
|
89
|
+
* Return a Ruby array of breakpoints found. Qtrue if no match found, but this
|
90
|
+
* file contains at least one breakpoint. Qnil if event triggered in a file
|
91
|
+
* that doesn't contain any breakpoints.
|
92
|
+
*/
|
93
|
+
static VALUE
|
94
|
+
match_breakpoints(VALUE self, const char *c_trace_path, int c_trace_lineno)
|
95
|
+
{
|
96
|
+
int i, j;
|
97
|
+
VALUE path_breakpoints_hash = rb_iv_get(self, "@breakpoints_cache");
|
98
|
+
VALUE breakpoints_paths = hash_get_keys(path_breakpoints_hash);
|
99
|
+
VALUE *c_breakpoints_paths = RARRAY_PTR(breakpoints_paths);
|
100
|
+
int breakpoints_paths_len = RARRAY_LEN(breakpoints_paths);
|
101
|
+
VALUE path_match = Qnil;
|
102
|
+
|
103
|
+
// Check the file paths of @breakpoints_cache
|
104
|
+
for (i = 0; i < breakpoints_paths_len; i++) {
|
105
|
+
VALUE breakpoint_path = c_breakpoints_paths[i];
|
106
|
+
char *c_breakpoint_path = rb_string_value_cstr(&breakpoint_path);
|
107
|
+
|
108
|
+
// Found matching file path, keep going and check for the line numbers
|
109
|
+
if (strcmp(c_trace_path, c_breakpoint_path) == 0) {
|
110
|
+
VALUE line_breakpoint_hash = rb_hash_aref(path_breakpoints_hash, breakpoint_path);
|
111
|
+
VALUE breakpoints_lines = hash_get_keys(line_breakpoint_hash);
|
112
|
+
VALUE *c_breakpoints_lines = RARRAY_PTR(breakpoints_lines);
|
113
|
+
int breakpoints_lines_len = RARRAY_LEN(breakpoints_lines);
|
114
|
+
path_match = Qtrue;
|
115
|
+
|
116
|
+
// Found matching breakpoints. Return the cached breakpoints array
|
117
|
+
for (j = 0; j < breakpoints_lines_len; j++) {
|
118
|
+
VALUE breakpoint_lineno = c_breakpoints_lines[j];
|
119
|
+
int c_breakpoint_lineno = NUM2INT(breakpoint_lineno);
|
120
|
+
|
121
|
+
if (c_trace_lineno == c_breakpoint_lineno) {
|
122
|
+
return rb_hash_aref(line_breakpoint_hash, breakpoint_lineno);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
return path_match;
|
129
|
+
}
|
130
|
+
|
131
|
+
/**
|
132
|
+
* line_trace_callback
|
133
|
+
* Callback function for thread line event tracing. It checks tracer#breakpoint_cache
|
134
|
+
* for any breakpoints trigger on current line called. Then trigger evaluation
|
135
|
+
* procedure if found matching breakpoints. It also skip breakpoints that are
|
136
|
+
* already marked completed.
|
137
|
+
*/
|
138
|
+
static void
|
139
|
+
line_trace_callback(rb_event_flag_t event, VALUE data, VALUE obj, ID mid, VALUE klass)
|
140
|
+
{
|
141
|
+
VALUE self = data;
|
142
|
+
const char *c_trace_path = rb_sourcefile();
|
143
|
+
int c_trace_lineno = rb_sourceline();
|
144
|
+
VALUE trace_binding;
|
145
|
+
VALUE call_stack_bindings;
|
146
|
+
|
147
|
+
int i;
|
148
|
+
VALUE matching_result = match_breakpoints(self, c_trace_path, c_trace_lineno);
|
149
|
+
VALUE *c_matching_breakpoints;
|
150
|
+
VALUE matching_breakpoint;
|
151
|
+
int matching_breakpoints_len;
|
152
|
+
|
153
|
+
// If matching result isn't an array, it means we're in completely wrong file,
|
154
|
+
// or not on the right line. Turn line tracing off if we're in wrong file.
|
155
|
+
if (!RB_TYPE_P(matching_result, T_ARRAY)) {
|
156
|
+
if (!RTEST(matching_result)) {
|
157
|
+
disable_line_trace_for_thread(Qnil);
|
158
|
+
}
|
159
|
+
return;
|
160
|
+
}
|
161
|
+
|
162
|
+
c_matching_breakpoints = RARRAY_PTR(matching_result);
|
163
|
+
matching_breakpoints_len = RARRAY_LEN(matching_result);
|
164
|
+
trace_binding = rb_binding_new();
|
165
|
+
call_stack_bindings = rb_funcall(trace_binding, rb_intern("callers"), 0);
|
166
|
+
rb_ary_pop(call_stack_bindings);
|
167
|
+
|
168
|
+
// Evaluate each of the matching breakpoint
|
169
|
+
for (i = 0; i < matching_breakpoints_len; i++) {
|
170
|
+
matching_breakpoint = c_matching_breakpoints[i];
|
171
|
+
rb_funcall(self, rb_intern("eval_breakpoint"), 2, matching_breakpoint, call_stack_bindings);
|
172
|
+
}
|
173
|
+
|
174
|
+
return;
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
* disable_line_trace_for_thread
|
179
|
+
* Turn off line event trace hook for a given thread. If no thread is given, it
|
180
|
+
* turns off line event trace hook in current thread. It only takes action if
|
181
|
+
* the thread has a thread variable "gcloud_line_trace_set" that's true.
|
182
|
+
*/
|
183
|
+
static VALUE
|
184
|
+
disable_line_trace_for_thread(VALUE thread)
|
185
|
+
{
|
186
|
+
VALUE thread_variables_hash;
|
187
|
+
VALUE line_trace_set;
|
188
|
+
|
189
|
+
if (!RTEST(thread)) {
|
190
|
+
thread = rb_thread_current();
|
191
|
+
}
|
192
|
+
thread_variables_hash = rb_ivar_get(thread, rb_intern("locals"));
|
193
|
+
line_trace_set = rb_hash_aref(thread_variables_hash, rb_str_new2("gcloud_line_trace_set"));
|
194
|
+
|
195
|
+
if (RTEST(line_trace_set)) {
|
196
|
+
rb_thread_remove_event_hook(thread, line_trace_callback);
|
197
|
+
rb_hash_aset(thread_variables_hash, rb_str_new2("gcloud_line_trace_set"), Qfalse);
|
198
|
+
}
|
199
|
+
|
200
|
+
return Qnil;
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* enable_line_trace_for_thread
|
205
|
+
* Turn on line even trace for current thread. Also set a flag
|
206
|
+
* "gcloud_line_trace_set" to Qtrue in current thread's thread variable.
|
207
|
+
*/
|
208
|
+
static VALUE
|
209
|
+
enable_line_trace_for_thread(VALUE self)
|
210
|
+
{
|
211
|
+
VALUE current_thread = rb_thread_current();
|
212
|
+
VALUE thread_variables_hash = rb_ivar_get(current_thread, rb_intern("locals"));
|
213
|
+
VALUE line_trace_set = rb_hash_aref(thread_variables_hash, rb_str_new2("gcloud_line_trace_set"));
|
214
|
+
|
215
|
+
if (!RTEST(line_trace_set)) {
|
216
|
+
rb_thread_add_event_hook(current_thread, line_trace_callback, RUBY_EVENT_LINE, self);
|
217
|
+
rb_hash_aset(thread_variables_hash, rb_str_new2("gcloud_line_trace_set"), Qtrue);
|
218
|
+
}
|
219
|
+
|
220
|
+
return Qnil;
|
221
|
+
}
|
222
|
+
|
223
|
+
/**
|
224
|
+
* return_trace_callback
|
225
|
+
* Callback function for tracer#return_tracepoint. It gets called on
|
226
|
+
* RUBY_EVENT_END, RUBY_EVENT_RETURN, RUBY_EVENT_C_RETURN, and
|
227
|
+
* RUBY_EVENT_B_RETURN events. It keeps line tracing consistent when Ruby
|
228
|
+
* program counter interleaves files. Everytime called, it checks caller stack
|
229
|
+
* frame's file path, if it matches any of the breakpoints, it turns line
|
230
|
+
* event tracing back on. It also decrements tracer#return_tracepoint_counter
|
231
|
+
* everytime called. When the counter is at 0, it disables itself, which should
|
232
|
+
* be the same stack frame that the return_tracepoint is turned on.
|
233
|
+
*/
|
234
|
+
static void
|
235
|
+
return_trace_callback(void *data, rb_trace_arg_t *trace_arg)
|
236
|
+
{
|
237
|
+
VALUE match_found;
|
238
|
+
VALUE self = (VALUE) data;
|
239
|
+
VALUE caller_locations = rb_funcall(rb_mKernel, rb_intern("caller_locations"), 2, INT2NUM(0), INT2NUM(1));
|
240
|
+
VALUE *c_caller_locations;
|
241
|
+
VALUE caller_location;
|
242
|
+
VALUE caller_path;
|
243
|
+
|
244
|
+
if(!RTEST(caller_locations)) {
|
245
|
+
return;
|
246
|
+
}
|
247
|
+
|
248
|
+
c_caller_locations = RARRAY_PTR(caller_locations);
|
249
|
+
caller_location = c_caller_locations[0];
|
250
|
+
caller_path = rb_funcall(caller_location, rb_intern("absolute_path"), 0);
|
251
|
+
|
252
|
+
if(!RTEST(caller_path)) {
|
253
|
+
return;
|
254
|
+
}
|
255
|
+
|
256
|
+
match_found = match_breakpoints_files(self, caller_path);
|
257
|
+
|
258
|
+
if (match_found) {
|
259
|
+
enable_line_trace_for_thread(self);
|
260
|
+
}
|
261
|
+
|
262
|
+
return;
|
263
|
+
}
|
264
|
+
|
265
|
+
/**
|
266
|
+
* disable_return_trace_for_thread
|
267
|
+
* Turn off return events trace hook for a given thread. If no thread is given, it
|
268
|
+
* turns off line event trace hook in current thread. It only takes action if
|
269
|
+
* the thread has a thread variable "gcloud_return_trace_set" that's true.
|
270
|
+
*/
|
271
|
+
static VALUE
|
272
|
+
disable_return_trace_for_thread(VALUE thread)
|
273
|
+
{
|
274
|
+
VALUE thread_variables_hash;
|
275
|
+
VALUE return_trace_set;
|
276
|
+
|
277
|
+
if (!RTEST(thread)) {
|
278
|
+
thread = rb_thread_current();
|
279
|
+
}
|
280
|
+
thread_variables_hash = rb_ivar_get(thread, rb_intern("locals"));
|
281
|
+
return_trace_set = rb_hash_aref(thread_variables_hash, rb_str_new2("gcloud_return_trace_set"));
|
282
|
+
|
283
|
+
if (RTEST(return_trace_set)) {
|
284
|
+
rb_thread_remove_event_hook(thread, (rb_event_hook_func_t)return_trace_callback);
|
285
|
+
rb_hash_aset(thread_variables_hash, rb_str_new2("gcloud_return_trace_set"), Qfalse);
|
286
|
+
}
|
287
|
+
|
288
|
+
return Qnil;
|
289
|
+
}
|
290
|
+
|
291
|
+
/**
|
292
|
+
* enable_return_trace_for_thread
|
293
|
+
* Turn on return events trace for current thread. Also set a flag
|
294
|
+
* "gcloud_return_trace_set" to Qtrue in current thread's thread variable.
|
295
|
+
*/
|
296
|
+
static VALUE
|
297
|
+
enable_return_trace_for_thread(VALUE self)
|
298
|
+
{
|
299
|
+
VALUE current_thread = rb_thread_current();
|
300
|
+
VALUE thread_variables_hash = rb_ivar_get(current_thread, rb_intern("locals"));
|
301
|
+
VALUE return_trace_set = rb_hash_aref(thread_variables_hash, rb_str_new2("gcloud_return_trace_set"));
|
302
|
+
|
303
|
+
if (!RTEST(return_trace_set)) {
|
304
|
+
int return_tracepoint_event = RUBY_EVENT_END | RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN;
|
305
|
+
rb_thread_add_event_hook2(current_thread, (rb_event_hook_func_t)return_trace_callback, return_tracepoint_event, self, RUBY_EVENT_HOOK_FLAG_RAW_ARG | RUBY_EVENT_HOOK_FLAG_SAFE);
|
306
|
+
rb_hash_aset(thread_variables_hash, rb_str_new2("gcloud_return_trace_set"), Qtrue);
|
307
|
+
}
|
308
|
+
|
309
|
+
return Qnil;
|
310
|
+
}
|
311
|
+
|
312
|
+
/**
|
313
|
+
* file_tracepoint_callback
|
314
|
+
* Callback function for tracer#file_tracepoint. It gets called on
|
315
|
+
* RUBY_EVENT_CLASS, RUBY_EVENT_CALL, RUBY_EVENT_C_CALL, and RUBY_EVENT_B_CALL
|
316
|
+
* events. It check if any breakpoints matches current file the VM program counter
|
317
|
+
* is in, and turn on line event tracing for that thread. Otherwise turn off
|
318
|
+
* line tracing if in wrong file. The first time it turns on line even tracing,
|
319
|
+
* it also turns on tracer#return_tracepoint to maintain line tracing
|
320
|
+
* consistency when file execution interleaves. If return_tracepoint is already
|
321
|
+
* on, it increments tracer#return_tracepoint_counter.
|
322
|
+
*/
|
323
|
+
static void
|
324
|
+
file_tracepoint_callback(VALUE tracepoint, void *data)
|
325
|
+
{
|
326
|
+
VALUE self = (VALUE) data;
|
327
|
+
rb_trace_arg_t *tracepoint_arg = rb_tracearg_from_tracepoint(tracepoint);
|
328
|
+
VALUE tracepoint_path = rb_tracearg_path(tracepoint_arg);
|
329
|
+
VALUE match_found;
|
330
|
+
|
331
|
+
if (!RB_TYPE_P(tracepoint_path, T_STRING))
|
332
|
+
return;
|
333
|
+
|
334
|
+
match_found = match_breakpoints_files(self, tracepoint_path);
|
335
|
+
|
336
|
+
if (match_found) {
|
337
|
+
enable_line_trace_for_thread(self);
|
338
|
+
enable_return_trace_for_thread(self);
|
339
|
+
}
|
340
|
+
else {
|
341
|
+
disable_line_trace_for_thread(Qnil);
|
342
|
+
}
|
343
|
+
|
344
|
+
return;
|
345
|
+
}
|
346
|
+
|
347
|
+
#ifdef RUBY_EVENT_FIBER_SWITCH
|
348
|
+
static void
|
349
|
+
fiber_tracepoint_callback(VALUE tracepoint, void *data)
|
350
|
+
{
|
351
|
+
VALUE self = (VALUE) data;
|
352
|
+
rb_trace_arg_t *tracepoint_arg = rb_tracearg_from_tracepoint(tracepoint);
|
353
|
+
VALUE tracepoint_lineno = rb_tracearg_lineno(tracepoint_arg);
|
354
|
+
int c_tracepoint_lineno = NUM2INT(tracepoint_lineno);
|
355
|
+
|
356
|
+
// Only if lineno is greater than 0, then we know this event is triggered from
|
357
|
+
// fiber execution, and we blindly starts line_trace.
|
358
|
+
if (c_tracepoint_lineno > 0) {
|
359
|
+
enable_line_trace_for_thread(self);
|
360
|
+
}
|
361
|
+
|
362
|
+
return;
|
363
|
+
}
|
364
|
+
#endif
|
365
|
+
|
366
|
+
/**
|
367
|
+
* register_tracepoint
|
368
|
+
* Helper function to create a new tracepoint and set the instance varaible on
|
369
|
+
* tracer if it doesn't exist already. Returns the existing tracepoint or the
|
370
|
+
* newly created tracepoint.
|
371
|
+
*/
|
372
|
+
static VALUE
|
373
|
+
register_tracepoint(VALUE self, int event, const char *instance_variable_name, void (*call_back_func)(VALUE, void *))
|
374
|
+
{
|
375
|
+
VALUE tracepoint = rb_iv_get(self, instance_variable_name);
|
376
|
+
|
377
|
+
if (event && !RTEST(tracepoint)) {
|
378
|
+
tracepoint = rb_tracepoint_new(Qnil, event, call_back_func, (void *)self);
|
379
|
+
rb_iv_set(self, instance_variable_name, tracepoint);
|
380
|
+
}
|
381
|
+
|
382
|
+
return tracepoint;
|
383
|
+
}
|
384
|
+
|
385
|
+
/**
|
386
|
+
* rb_disable_traces
|
387
|
+
* This is implmenetation of Tracer#disable_traces methods. It disables
|
388
|
+
* tracer#file_tracepoint, tracer#fiber_tracepoint, return even tracing, and
|
389
|
+
* line event tracing for all threads.
|
390
|
+
*/
|
391
|
+
static VALUE
|
392
|
+
rb_disable_traces(VALUE self)
|
393
|
+
{
|
394
|
+
VALUE file_tracepoint;
|
395
|
+
VALUE fiber_tracepoint;
|
396
|
+
VALUE threads;
|
397
|
+
VALUE *c_threads;
|
398
|
+
int c_threads_len;
|
399
|
+
VALUE thread;
|
400
|
+
int i;
|
401
|
+
|
402
|
+
file_tracepoint = rb_iv_get(self, "@file_tracepoint");
|
403
|
+
threads = rb_funcall(rb_cThread, rb_intern("list"), 0);
|
404
|
+
c_threads_len = RARRAY_LEN(threads);
|
405
|
+
c_threads = RARRAY_PTR(threads);
|
406
|
+
UNUSED(fiber_tracepoint);
|
407
|
+
|
408
|
+
if (RTEST(file_tracepoint) && RTEST(rb_tracepoint_enabled_p(file_tracepoint)))
|
409
|
+
rb_tracepoint_disable(file_tracepoint);
|
410
|
+
|
411
|
+
#ifdef RUBY_EVENT_FIBER_SWITCH
|
412
|
+
fiber_tracepoint= rb_iv_get(self, "@fiber_tracepoint");
|
413
|
+
if (RTEST(fiber_tracepoint) && RTEST(rb_tracepoint_enabled_p(fiber_tracepoint)))
|
414
|
+
rb_tracepoint_disable(fiber_tracepoint);
|
415
|
+
#endif
|
416
|
+
|
417
|
+
for (i = 0; i < c_threads_len; i++) {
|
418
|
+
thread = c_threads[i];
|
419
|
+
if (RTEST(rb_funcall(thread, rb_intern("alive?"), 0))) {
|
420
|
+
disable_line_trace_for_thread(thread);
|
421
|
+
disable_return_trace_for_thread(thread);
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
425
|
+
return Qnil;
|
426
|
+
}
|
427
|
+
|
428
|
+
/**
|
429
|
+
* rb_enable_traces
|
430
|
+
* This is the implementation of Tracer#enable_traces methods. It creates
|
431
|
+
* the tracer#file_tracepoints and tracer#fiber_tracepoints for the first time
|
432
|
+
* called. Then it also enables them immediately upon creation.
|
433
|
+
*/
|
434
|
+
static VALUE
|
435
|
+
rb_enable_traces(VALUE self)
|
436
|
+
{
|
437
|
+
VALUE file_tracepoint;
|
438
|
+
VALUE fiber_tracepoint;
|
439
|
+
|
440
|
+
file_tracepoint = register_tracepoint(self, FILE_TRACEPOINT_EVENT, "@file_tracepoint", file_tracepoint_callback);
|
441
|
+
UNUSED(fiber_tracepoint);
|
442
|
+
|
443
|
+
// Immediately activate file tracepoint and fiber tracepoint
|
444
|
+
if (RTEST(file_tracepoint) && !RTEST(rb_tracepoint_enabled_p(file_tracepoint))) {
|
445
|
+
rb_tracepoint_enable(file_tracepoint);
|
446
|
+
}
|
447
|
+
#ifdef RUBY_EVENT_FIBER_SWITCH
|
448
|
+
fiber_tracepoint = register_tracepoint(self, RUBY_EVENT_FIBER_SWITCH, "@fiber_tracepoint", fiber_tracepoint_callback);
|
449
|
+
if (RTEST(fiber_tracepoint) && !RTEST(rb_tracepoint_enabled_p(fiber_tracepoint))) {
|
450
|
+
rb_tracepoint_enable(fiber_tracepoint);
|
451
|
+
}
|
452
|
+
#endif
|
453
|
+
return Qnil;
|
454
|
+
}
|
455
|
+
|
456
|
+
/**
|
457
|
+
* rb_disable_traces_for_thread
|
458
|
+
* It disables line tracing and return event tracing for current thread.
|
459
|
+
*/
|
460
|
+
static VALUE
|
461
|
+
rb_disable_traces_for_thread(VALUE self)
|
462
|
+
{
|
463
|
+
VALUE thread = rb_thread_current();
|
464
|
+
disable_line_trace_for_thread(thread);
|
465
|
+
disable_return_trace_for_thread(thread);
|
466
|
+
|
467
|
+
return Qnil;
|
468
|
+
}
|
469
|
+
|
470
|
+
void
|
471
|
+
Init_tracer(VALUE mDebugger)
|
472
|
+
{
|
473
|
+
VALUE cTracer = rb_define_class_under(mDebugger, "Tracer", rb_cObject);
|
474
|
+
|
475
|
+
rb_define_method(cTracer, "enable_traces", rb_enable_traces, 0);
|
476
|
+
rb_define_method(cTracer, "disable_traces", rb_disable_traces, 0);
|
477
|
+
rb_define_method(cTracer, "disable_traces_for_thread", rb_disable_traces_for_thread, 0);
|
478
|
+
}
|