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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +201 -0
  4. data/README.md +56 -0
  5. data/ext/google/cloud/debugger/debugger_c/debugger.c +31 -0
  6. data/ext/google/cloud/debugger/debugger_c/debugger.h +26 -0
  7. data/ext/google/cloud/debugger/debugger_c/evaluator.c +78 -0
  8. data/ext/google/cloud/debugger/debugger_c/evaluator.h +25 -0
  9. data/ext/google/cloud/debugger/debugger_c/extconf.rb +22 -0
  10. data/ext/google/cloud/debugger/debugger_c/tracer.c +478 -0
  11. data/ext/google/cloud/debugger/debugger_c/tracer.h +31 -0
  12. data/lib/google-cloud-debugger.rb +121 -0
  13. data/lib/google/cloud/debugger.rb +379 -0
  14. data/lib/google/cloud/debugger/agent.rb +204 -0
  15. data/lib/google/cloud/debugger/async_actor.rb +290 -0
  16. data/lib/google/cloud/debugger/breakpoint.rb +382 -0
  17. data/lib/google/cloud/debugger/breakpoint/evaluator.rb +1113 -0
  18. data/lib/google/cloud/debugger/breakpoint/source_location.rb +75 -0
  19. data/lib/google/cloud/debugger/breakpoint/stack_frame.rb +109 -0
  20. data/lib/google/cloud/debugger/breakpoint/variable.rb +304 -0
  21. data/lib/google/cloud/debugger/breakpoint_manager.rb +217 -0
  22. data/lib/google/cloud/debugger/credentials.rb +41 -0
  23. data/lib/google/cloud/debugger/debuggee.rb +204 -0
  24. data/lib/google/cloud/debugger/debuggee/app_uniquifier_generator.rb +78 -0
  25. data/lib/google/cloud/debugger/middleware.rb +77 -0
  26. data/lib/google/cloud/debugger/project.rb +135 -0
  27. data/lib/google/cloud/debugger/rails.rb +141 -0
  28. data/lib/google/cloud/debugger/service.rb +130 -0
  29. data/lib/google/cloud/debugger/tracer.rb +165 -0
  30. data/lib/google/cloud/debugger/transmitter.rb +129 -0
  31. data/lib/google/cloud/debugger/v2.rb +15 -0
  32. data/lib/google/cloud/debugger/v2/controller2_client.rb +299 -0
  33. data/lib/google/cloud/debugger/v2/controller2_client_config.json +43 -0
  34. data/lib/google/cloud/debugger/v2/debugger2_client.rb +378 -0
  35. data/lib/google/cloud/debugger/v2/debugger2_client_config.json +53 -0
  36. data/lib/google/cloud/debugger/v2/doc/google/devtools/clouddebugger/v2/data.rb +441 -0
  37. data/lib/google/cloud/debugger/v2/doc/google/devtools/clouddebugger/v2/debugger.rb +151 -0
  38. data/lib/google/cloud/debugger/v2/doc/google/devtools/source/v1/source_context.rb +161 -0
  39. data/lib/google/cloud/debugger/v2/doc/google/protobuf/timestamp.rb +81 -0
  40. data/lib/google/cloud/debugger/version.rb +22 -0
  41. data/lib/google/devtools/clouddebugger/v2/controller_pb.rb +47 -0
  42. data/lib/google/devtools/clouddebugger/v2/controller_services_pb.rb +97 -0
  43. data/lib/google/devtools/clouddebugger/v2/data_pb.rb +105 -0
  44. data/lib/google/devtools/clouddebugger/v2/debugger_pb.rb +74 -0
  45. data/lib/google/devtools/clouddebugger/v2/debugger_services_pb.rb +64 -0
  46. data/lib/google/devtools/source/v1/source_context_pb.rb +89 -0
  47. 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
+ }