module Kernel

Public Instance Methods

exec_trace() click to toggle source

Global function that begins tracing

VALUE
exec_trace(VALUE self)
{
  // Capture current thread ID to ensure we don't capture frames from other
  // threads.
  tracer.thread = rb_thread_current();

  // Start listening for call events
  rb_add_event_hook((rb_event_hook_func_t)trace_hook,
                    RUBY_EVENT_CALL | RUBY_EVENT_C_CALL | RUBY_EVENT_RETURN |
                      RUBY_EVENT_C_RETURN,
                    Qnil);

  // Call passed in block, ensure trace hook is removed
  rb_ensure(rb_yield, Qnil, exec_trace_ensure, self);

  VALUE top_level_frame_ary = rb_ary_new();

  for (uint64_t i = 0; i < tracer.top_frame_used; i++) {
    VALUE frame_ary = rb_ary_new();
    create_frame_array(frame_ary, tracer.top_frames[i]);
    rb_ary_push(top_level_frame_ary, frame_ary);

    // Cleanup malloc'd memory
    cleanup(tracer.top_frames[i]);
  }

  // Cleanup for another run
  tracer.top_frame_used = 0;
  tracer.last_frame = NULL;
  memset(tracer.top_frames, 0, sizeof(tracer.top_frames));

  return top_level_frame_ary;
}