Example #1
0
static void
line_event(VALUE trace_point, void *data)
{
  VALUE breakpoint, file, line, binding, self;
  int moved = 0;

  EVENT_SETUP

  breakpoint = Qnil;
  file    = rb_tracearg_path(trace_arg);
  line    = rb_tracearg_lineno(trace_arg);
  binding = rb_tracearg_binding(trace_arg);
  self    = rb_tracearg_self(trace_arg);

  EVENT_COMMON

  if (dc->calced_stack_size == 0) dc->calced_stack_size++;

  if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
      dc->last_file != rb_tracearg_path(trace_arg))
  {
    moved = 1;
  }

  if (RTEST(tracing))
    call_at_tracing(context, dc, file, line);

  if (moved || !CTX_FL_TEST(dc, CTX_FL_FORCE_MOVE))
  {
    dc->steps = dc->steps <= 0 ? -1 : dc->steps - 1;
    if (dc->calced_stack_size <= dc->dest_frame)
    {
      dc->lines = dc->lines <= 0 ? -1 : dc->lines - 1;
      if (dc->calced_stack_size < dc->dest_frame)
      {
        dc->dest_frame = dc->calced_stack_size;
        rb_funcall(mByebug, rb_intern("puts"), 1,
          rb_str_new2("Next went up a frame because previous frame finished\n"));
      }
    }
  }

  if (dc->steps == 0 || dc->lines == 0 ||
      (CTX_FL_TEST(dc, CTX_FL_ENABLE_BKPT) &&
      (!NIL_P(
       breakpoint = find_breakpoint_by_pos(bb_breakpoints(self), file, line, binding)))))
  {
    call_at_line_check(context, dc, breakpoint, file, line);
  }

  cleanup(dc);
}
Example #2
0
/*
 * Holds thread execution while another thread is active.
 *
 * Thanks to this, all threads are "frozen" while the user is typing commands.
 */
void
acquire_lock(debug_context_t * dc)
{
  while ((!NIL_P(locker) && locker != rb_thread_current())
         || CTX_FL_TEST(dc, CTX_FL_SUSPEND))
  {
    add_to_locked(rb_thread_current());
    rb_thread_stop();

    if (CTX_FL_TEST(dc, CTX_FL_SUSPEND))
      CTX_FL_SET(dc, CTX_FL_WAS_RUNNING);
  }

  locker = rb_thread_current();
}
Example #3
0
/*
 *  call-seq:
 *    context.dead? -> bool
 *
 *  Returns +true+ if context doesn't represent a live context and is created
 *  during post-mortem exception handling.
 */
static inline VALUE
Context_dead(VALUE self)
{
  debug_context_t *context;
  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_DEAD) ? Qtrue : Qfalse;
}
Example #4
0
static VALUE
Context_stop_reason(VALUE self)
{
    debug_context_t *context;
    const char *symbol;

    Data_Get_Struct(self, debug_context_t, context);
    
    switch(context->stop_reason)
    {
        case CTX_STOP_STEP:
            symbol = "step";
            break;
        case CTX_STOP_BREAKPOINT:
            symbol = "breakpoint";
            break;
        case CTX_STOP_CATCHPOINT:
            symbol = "catchpoint";
            break;
        case CTX_STOP_NONE:
        default:
            symbol = "none";
    }
    if(CTX_FL_TEST(context, CTX_FL_DEAD))
        symbol = "post-mortem";
    
    return ID2SYM(rb_intern(symbol));
}
Example #5
0
File: byebug.c Project: Xifip/modr
static void
call_event(VALUE trace_point, void *data)
{
  VALUE breakpoint, klass, msym, mid, binding, self, file, line;

  EVENT_SETUP

  dc->calced_stack_size++;

  if (CTX_FL_TEST(dc, CTX_FL_STOP_ON_RET))
    dc->steps_out = dc->steps_out <= 0 ? -1 : dc->steps_out + 1;

  EVENT_COMMON

  breakpoint = Qnil;
  klass   = rb_tracearg_defined_class(trace_arg);
  msym    = rb_tracearg_method_id(trace_arg);
  mid     = NIL_P(msym) ? Qnil : SYM2ID(msym);
  binding = rb_tracearg_binding(trace_arg);
  self    = rb_tracearg_self(trace_arg);
  file    = rb_tracearg_path(trace_arg);
  line    = rb_tracearg_lineno(trace_arg);

  breakpoint = find_breakpoint_by_method(breakpoints, klass, mid, binding, self);
  if (breakpoint != Qnil)
  {
    call_at_breakpoint(context, dc, breakpoint);
    call_at_line(context, dc, file, line);
  }

  cleanup(dc);
}
Example #6
0
/*
 *  call-seq:
 *    context.tracing -> bool
 *
 *  Returns the tracing flag for the current context.
 */
static VALUE
Context_tracing(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_TRACING) ? Qtrue : Qfalse;
}
Example #7
0
/*
 *  call-seq:
 *    context.resume -> nil
 *
 *  Resumes thread from the suspended mode.
 */
static VALUE
Context_resume(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  if (!CTX_FL_TEST(context, CTX_FL_SUSPEND))
    return Qnil;

  CTX_FL_UNSET(context, CTX_FL_SUSPEND);

  if (CTX_FL_TEST(context, CTX_FL_WAS_RUNNING))
    rb_thread_wakeup(context->thread);

  return Qnil;
}
Example #8
0
/*
 *  call-seq:
 *    context.ignored? -> bool
 *
 *  Returns the ignore flag for the context, which marks whether the associated
 *  thread is ignored while debugging.
 */
static inline VALUE
Context_ignored(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
}
Example #9
0
extern VALUE 
Context_ignored(VALUE self) 
{
  debug_context_t *context;

  if (self == Qnil) return Qtrue;
  Data_Get_Struct(self, debug_context_t, context);
  return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
}
Example #10
0
/*
 *  call-seq:
 *    context.suspended? -> bool
 *
 *  Returns +true+ if the thread is suspended by debugger.
 */
static VALUE
Context_is_suspended(VALUE self)
{
  debug_context_t *context;

  Data_Get_Struct(self, debug_context_t, context);

  return CTX_FL_TEST(context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
}
Example #11
0
static void
return_event(VALUE trace_point, void *data)
{
  VALUE brkpnt, file, line, binding;

  EVENT_SETUP;

  RETURN_EVENT_SETUP;

  if ((dc->steps_out == 0) && (CTX_FL_TEST(dc, CTX_FL_STOP_ON_RET)))
  {
    reset_stepping_stop_points(dc);

    call_at_return(context, dc, rb_tracearg_return_value(trace_arg));
  }
  else if (!NIL_P(breakpoints))
  {
    file = rb_tracearg_path(trace_arg);
    /*
     * @todo Sometimes the TracePoint API gives some return events without
     * file:line information, so we need to guard for nil until we know what's
     * going on. This happens, for example, with active_support core extensions:
     *
     * [#7] call@.../core_ext/numeric/conversions.rb:124 Fixnum#to_s
     *  [#7] b_call@.../core_ext/numeric/conversions.rb:124 BigDecimal#to_s
     *   [#7] line@.../core_ext/numeric/conversions.rb:125 BigDecimal#to_s
     *   [#7] c_call@.../core_ext/numeric/conversions.rb:125 Kernel#is_a?
     *    [#7] c_return@.../core_ext/numeric/conversions.rb:125 Kernel#is_a?
     *   [#7] line@.../core_ext/numeric/conversions.rb:131 BigDecimal#to_s
     *   [#7] c_call@.../core_ext/numeric/conversions.rb:131 Fixnum#to_default_s
     *    [#7] c_return@.../core_ext/numeric/conversions.rb:131 Fixnum#to_default_s
     *   [#7] b_return@/hort/core_ext/numeric/conversions.rb:133 BigDecimal#to_s
     *  [#7] return@:0 Fixnum#to_s # => This guy...
     */
    if (!NIL_P(file))
    {
      line = rb_tracearg_lineno(trace_arg);
      binding = rb_tracearg_binding(trace_arg);

      brkpnt = find_breakpoint_by_pos(breakpoints, file, line, binding);

      if (!NIL_P(brkpnt))
        call_at_return(context, dc, rb_tracearg_return_value(trace_arg));
    }
  }

  RETURN_EVENT_TEARDOWN;

  EVENT_TEARDOWN;
}
Example #12
0
static void
return_event(VALUE trace_point, void *data)
{
  EVENT_SETUP;

  RETURN_EVENT_SETUP;

  if ((dc->steps_out == 0) && (CTX_FL_TEST(dc, CTX_FL_STOP_ON_RET)))
  {
    reset_stepping_stop_points(dc);

    call_at_return(context, dc, rb_tracearg_return_value(trace_arg));
  }

  RETURN_EVENT_TEARDOWN;

  EVENT_TEARDOWN;
}
Example #13
0
static void
end_event(VALUE trace_point, void *data)
{
  EVENT_SETUP;

  RETURN_EVENT_SETUP;

  if ((dc->steps_out == 0) && (CTX_FL_TEST(dc, CTX_FL_STOP_ON_RET)))
  {
    reset_stepping_stop_points(dc);

    call_at_end(context, dc);
  }

  RETURN_EVENT_TEARDOWN;

  EVENT_TEARDOWN;
}
Example #14
0
static void
line_event(VALUE trace_point, void *data)
{
  VALUE brkpnt, file, line, binding;

  EVENT_SETUP;

  file = rb_tracearg_path(trace_arg);
  line = rb_tracearg_lineno(trace_arg);
  binding = rb_tracearg_binding(trace_arg);

  if (RTEST(tracing))
    call_at_tracing(context, dc);

  if (!CTX_FL_TEST(dc, CTX_FL_IGNORE_STEPS))
    dc->steps = dc->steps <= 0 ? -1 : dc->steps - 1;

  if (dc->calced_stack_size <= dc->dest_frame)
  {
    dc->dest_frame = dc->calced_stack_size;
    CTX_FL_UNSET(dc, CTX_FL_IGNORE_STEPS);

    dc->lines = dc->lines <= 0 ? -1 : dc->lines - 1;
  }

  if (dc->steps == 0 || dc->lines == 0)
    call_at_line_check(context, dc, Qnil);
  else
  {
    brkpnt = Qnil;

    if (!NIL_P(breakpoints))
      brkpnt = find_breakpoint_by_pos(breakpoints, file, line, binding);

    if (!NIL_P(brkpnt))
      call_at_line_check(context, dc, brkpnt);
  }

  EVENT_TEARDOWN;
}
Example #15
0
VALUE
check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid, VALUE self)
{
    VALUE breakpoint;
    int i;

    if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
        return Qnil;

    if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid, self))
        return debug_context->breakpoint;

    if(RARRAY_LEN(rdebug_breakpoints) == 0)
        return Qnil;
    for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
    {
        breakpoint = rb_ary_entry(rdebug_breakpoints, i);
        if(check_breakpoint_by_method(breakpoint, klass, mid, self))
            return breakpoint;
    }
    return Qnil;
}
Example #16
0
VALUE
check_breakpoints_by_pos(debug_context_t *debug_context, const char *file, int line)
{
    VALUE breakpoint;
    int i;

    if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
        return Qnil;

    if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
        return debug_context->breakpoint;

    if(RARRAY_LEN(rdebug_breakpoints) == 0)
        return Qnil;
    for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
    {
        breakpoint = rb_ary_entry(rdebug_breakpoints, i);
        if(check_breakpoint_by_pos(breakpoint, file, line))
            return breakpoint;
    }
    return Qnil;
}
Example #17
0
static void
return_event(VALUE trace_point, void *data)
{
  EVENT_SETUP;

  dc->calced_stack_size--;

  if (dc->steps_out == 1)
    dc->steps = 1;
  else if ((dc->steps_out == 0) && (CTX_FL_TEST(dc, CTX_FL_STOP_ON_RET)))
  {
    VALUE file, line;

    reset_stepping_stop_points(dc);
    file = rb_tracearg_path(trace_arg);
    line = rb_tracearg_lineno(trace_arg);
    call_at_return(context, dc, file, line);
  }

  dc->steps_out = dc->steps_out <= 0 ? -1 : dc->steps_out - 1;

  EVENT_TEARDOWN;
}
Example #18
0
File: byebug.c Project: Xifip/modr
static int
trace_common(rb_trace_arg_t *trace_arg, debug_context_t *dc)
{
  /* return if thread marked as 'ignored', like byebug's control thread */
  if (CTX_FL_TEST(dc, CTX_FL_IGNORE))
  {
    cleanup(dc);
    return 0;
  }

  halt_while_other_thread_is_active(dc);

  /* Get the lock! */
  locker = rb_thread_current();

  /* Many events per line, but only *one* breakpoint */
  if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
      dc->last_file != rb_tracearg_path(trace_arg))
  {
    CTX_FL_SET(dc, CTX_FL_ENABLE_BKPT);
  }

  return 1;
}