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; }
int ruby_cleanup(int ex) { int state; volatile VALUE errs[2]; rb_thread_t *th = GET_THREAD(); int nerr; errs[1] = th->errinfo; th->safe_level = 0; Init_stack((void*)&errs[STACK_UPPER(errs, 0, 1)]); PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { SAVE_ROOT_JMPBUF(th, ruby_finalize_0()); } POP_TAG(); errs[0] = th->errinfo; PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all()); } else if (ex == 0) { ex = state; } th->errinfo = errs[1]; ex = error_handle(ex); ruby_finalize_1(); POP_TAG(); rb_thread_stop_timer_thread(); for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) { VALUE err = errs[nerr]; if (!RTEST(err)) continue; /* th->errinfo contains a NODE while break'ing */ if (TYPE(err) == T_NODE) continue; if (rb_obj_is_kind_of(err, rb_eSystemExit)) { return sysexit_status(err); } else if (rb_obj_is_kind_of(err, rb_eSignal)) { VALUE sig = rb_iv_get(err, "signo"); ruby_default_signal(NUM2INT(sig)); } else if (ex == 0) { ex = 1; } } #if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1 switch (ex) { #if EXIT_SUCCESS != 0 case 0: return EXIT_SUCCESS; #endif #if EXIT_FAILURE != 1 case 1: return EXIT_FAILURE; #endif } #endif return ex; }