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; }
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; }
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; }
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; }