Beispiel #1
0
VALUE
rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg)
{
    volatile int raised;
    volatile int outer_state;
    VALUE result = Qnil;
    rb_thread_t *th = GET_THREAD();
    int state;
    const int tracing = th->trace_arg ? 1 : 0;
    rb_trace_arg_t dummy_trace_arg;
    dummy_trace_arg.event = 0;

    if (!tracing) th->vm->trace_running++;
    if (!th->trace_arg) th->trace_arg = &dummy_trace_arg;

    raised = rb_threadptr_reset_raised(th);
    outer_state = th->state;
    th->state = 0;

    TH_PUSH_TAG(th);
    if ((state = TH_EXEC_TAG()) == 0) {
        result = (*func)(arg);
    }
    TH_POP_TAG();

    if (raised) {
        rb_threadptr_set_raised(th);
    }

    if (th->trace_arg == &dummy_trace_arg) th->trace_arg = 0;
    if (!tracing) th->vm->trace_running--;

    if (state) {
        JUMP_TAG(state);
    }

    th->state = outer_state;
    return result;
}
Beispiel #2
0
static int
exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg, int can_clean_hooks)
{
    int state;
    volatile int raised;

    if (UNLIKELY(list->need_clean > 0) && can_clean_hooks) {
	clean_hooks(list);
    }

    raised = rb_threadptr_reset_raised(th);

    /* TODO: Support !RUBY_EVENT_HOOK_FLAG_SAFE hooks */

    TH_PUSH_TAG(th);
    if ((state = TH_EXEC_TAG()) == 0) {
	rb_event_hook_t *hook;

	for (hook = list->hooks; hook; hook = hook->next) {
	    if (LIKELY(!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED)) && (trace_arg->event & hook->events)) {
		if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_RAW_ARG)) {
		    (*hook->func)(trace_arg->event, hook->data, trace_arg->self, trace_arg->id, trace_arg->klass);
		}
		else {
		    (*((rb_event_hook_raw_arg_func_t)hook->func))(hook->data, trace_arg);
		}
	    }
	}
    }
    TH_POP_TAG();

    if (raised) {
	rb_threadptr_set_raised(th);
    }

    return state;
}
Beispiel #3
0
static int
exec_hooks_protected(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg)
{
    int state;
    volatile int raised;

    if (exec_hooks_precheck(th, list, trace_arg) == 0) return 0;

    raised = rb_threadptr_reset_raised(th);

    /* TODO: Support !RUBY_EVENT_HOOK_FLAG_SAFE hooks */

    TH_PUSH_TAG(th);
    if ((state = TH_EXEC_TAG()) == 0) {
        exec_hooks_body(th, list, trace_arg);
    }
    TH_POP_TAG();

    if (raised) {
        rb_threadptr_set_raised(th);
    }

    return state;
}
Beispiel #4
0
static int
error_handle(int ex)
{
    int status = EXIT_FAILURE;
    rb_thread_t *th = GET_THREAD();

    if (rb_threadptr_set_raised(th))
	return EXIT_FAILURE;
    switch (ex & TAG_MASK) {
      case 0:
	status = EXIT_SUCCESS;
	break;

      case TAG_RETURN:
	error_pos();
	warn_print("unexpected return\n");
	break;
      case TAG_NEXT:
	error_pos();
	warn_print("unexpected next\n");
	break;
      case TAG_BREAK:
	error_pos();
	warn_print("unexpected break\n");
	break;
      case TAG_REDO:
	error_pos();
	warn_print("unexpected redo\n");
	break;
      case TAG_RETRY:
	error_pos();
	warn_print("retry outside of rescue clause\n");
	break;
      case TAG_THROW:
	/* TODO: fix me */
	error_pos();
	warn_print("unexpected throw\n");
	break;
      case TAG_RAISE: {
	VALUE errinfo = th->errinfo;
	if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
	    status = sysexit_status(errinfo);
	}
	else if (rb_obj_is_instance_of(errinfo, rb_eSignal) &&
		 rb_ivar_get(errinfo, id_signo) != INT2FIX(SIGSEGV)) {
	    /* no message when exiting by signal */
	}
	else {
	    error_print(th);
	}
	break;
      }
      case TAG_FATAL:
	error_print(th);
	break;
      default:
	unknown_longjmp_status(ex);
	break;
    }
    rb_threadptr_reset_raised(th);
    return status;
}