/** Runs the VM finalization processes. * * <code>END{}</code> and procs registered by <code>Kernel.#at_exit</code> are * executed here. See the Ruby language spec for more details. * * @note This function is allowed to raise an exception if an error occurred. */ void ruby_finalize(void) { ruby_finalize_0(); ruby_finalize_1(); }
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; }