Upgrade to Pro — share decks privately, control downloads, hide ads and more …

at_exit

 at_exit

Atsushi Tanaka

July 20, 2019
Tweet

More Decks by Atsushi Tanaka

Other Decks in Technology

Transcript

  1. lib/fluent/logger/fluent_logger.rb class FluentLogger < LoggerBase ộ def initialize(tag_prefix = nil,

    *args) super() ộ at_exit { close } end ộ def close @mon.synchronize { if @pending begin send_data(@pending) rescue => e set_last_error(e) @logger.error("FluentLogger: Can't send logs to #{connection_string}: #{$!}") call_buffer_overflow_handler(@pending) end end @con.close if connect? @con = nil @pending = nil } self end ộ
  2. lib/fluent/logger/fluent_logger.rb class FluentLogger < LoggerBase ộ def initialize(tag_prefix = nil,

    *args) super() ộ at_exit { close } end ộ def close @mon.synchronize { if @pending begin send_data(@pending) rescue => e set_last_error(e) @logger.error("FluentLogger: Can't send logs to #{connection_string}: #{$!}") call_buffer_overflow_handler(@pending) end end @con.close if connect? @con = nil @pending = nil } self end ộ MPHHFSͷॳظԽ
  3. lib/fluent/logger/fluent_logger.rb class FluentLogger < LoggerBase ộ def initialize(tag_prefix = nil,

    *args) super() ộ at_exit { close } end ộ def close @mon.synchronize { if @pending begin send_data(@pending) rescue => e set_last_error(e) @logger.error("FluentLogger: Can't send logs to #{connection_string}: #{$!}") call_buffer_overflow_handler(@pending) end end @con.close if connect? @con = nil @pending = nil } self end ộ ऴྃॲཧͷొ࿥
  4. lib/fluent/logger/fluent_logger.rb class FluentLogger < LoggerBase ộ def initialize(tag_prefix = nil,

    *args) super() ộ at_exit { close } end ộ def close @mon.synchronize { if @pending begin send_data(@pending) rescue => e set_last_error(e) @logger.error("FluentLogger: Can't send logs to #{connection_string}: #{$!}") call_buffer_overflow_handler(@pending) end end @con.close if connect? @con = nil @pending = nil } self end ộ ऴྃॲཧ
  5. lib/fluent/logger/fluent_logger.rb class FluentLogger < LoggerBase ộ def initialize(tag_prefix = nil,

    *args) super() ộ at_exit { close } end ộ def close @mon.synchronize { if @pending begin send_data(@pending) rescue => e set_last_error(e) @logger.error("FluentLogger: Can't send logs to #{connection_string}: #{$!}") call_buffer_overflow_handler(@pending) end end @con.close if connect? @con = nil @pending = nil } self end ộ ະॲཧͷϩάΛૹ৴͠ऴΘΔ·Ͱ଴ͭ
  6. eval_jump.c static VALUE rb_f_at_exit(void) { VALUE proc; if (!rb_block_given_p()) {

    rb_raise(rb_eArgError, "called without a block"); } proc = rb_block_proc(); rb_set_end_proc(rb_call_end_proc, proc); return proc; } void Init_jump(void) { rb_define_global_function("at_exit", rb_f_at_exit, 0); }
  7. eval_jump.c static VALUE rb_f_at_exit(void) { VALUE proc; if (!rb_block_given_p()) {

    rb_raise(rb_eArgError, "called without a block"); } proc = rb_block_proc(); rb_set_end_proc(rb_call_end_proc, proc); return proc; } void Init_jump(void) { rb_define_global_function("at_exit", rb_f_at_exit, 0); } at_exitͷఆٛ
  8. eval_jump.c static VALUE rb_f_at_exit(void) { VALUE proc; if (!rb_block_given_p()) {

    rb_raise(rb_eArgError, "called without a block"); } proc = rb_block_proc(); rb_set_end_proc(rb_call_end_proc, proc); return proc; } void Init_jump(void) { rb_define_global_function("at_exit", rb_f_at_exit, 0); } ϒϩοΫͷొ࿥
  9. eval_jump.c void rb_set_end_proc(void (*func)(VALUE), VALUE data) { struct end_proc_data *link

    = ALLOC(struct end_proc_data); struct end_proc_data **list; rb_thread_t *th = GET_THREAD(); if (th->top_wrapper) { list = &ephemeral_end_procs; } else { list = &end_procs; } link->next = *list; link->func = func; link->data = data; *list = link; }
  10. eval_jump.c void rb_set_end_proc(void (*func)(VALUE), VALUE data) { struct end_proc_data *link

    = ALLOC(struct end_proc_data); struct end_proc_data **list; rb_thread_t *th = GET_THREAD(); if (th->top_wrapper) { list = &ephemeral_end_procs; } else { list = &end_procs; } link->next = *list; link->func = func; link->data = data; *list = link; } Ϧετͷઌ಄ʹ௥Ճ
  11. main.c int main(int argc, char **argv) { #ifdef RUBY_DEBUG_ENV ruby_set_debug_option(getenv("RUBY_DEBUG"));

    #endif #ifdef HAVE_LOCALE_H setlocale(LC_CTYPE, ""); #endif ruby_sysinit(&argc, &argv); { RUBY_INIT_STACK; ruby_init(); return ruby_run_node(ruby_options(argc, argv)); } }
  12. main.c int main(int argc, char **argv) { #ifdef RUBY_DEBUG_ENV ruby_set_debug_option(getenv("RUBY_DEBUG"));

    #endif #ifdef HAVE_LOCALE_H setlocale(LC_CTYPE, ""); #endif ruby_sysinit(&argc, &argv); { RUBY_INIT_STACK; ruby_init(); return ruby_run_node(ruby_options(argc, argv)); } } εΫϦϓτΛ࣮ߦ
  13. eval.c /*! Runs the given compiled source and exits this

    process. * @retval 0 if successfully run the source * @retval non-zero if an error occurred. */ int ruby_run_node(void *n) { int status; if (!ruby_executable_node(n, &status)) { ruby_cleanup(0); return status; } return ruby_cleanup(ruby_exec_node(n)); }
  14. eval.c /*! Runs the given compiled source and exits this

    process. * @retval 0 if successfully run the source * @retval non-zero if an error occurred. */ int ruby_run_node(void *n) { int status; if (!ruby_executable_node(n, &status)) { ruby_cleanup(0); return status; } return ruby_cleanup(ruby_exec_node(n)); } ॲཧͷ࣮ମ
  15. eval.c /*! Runs the given compiled source and exits this

    process. * @retval 0 if successfully run the source * @retval non-zero if an error occurred. */ int ruby_run_node(void *n) { int status; if (!ruby_executable_node(n, &status)) { ruby_cleanup(0); return status; } return ruby_cleanup(ruby_exec_node(n)); } εΫϦϓτͷऴ୺ʹୡͨ͠
  16. eval.c /** Destructs the VM. * * Runs the VM

    finalization processes as well as ruby_finalize(), and * resources used by the VM. * * @param ex Default value to the return value. * @return If an error occurred returns a non-zero. If otherwise, retur * given ex. * @note This function does not raise any exception. */ int ruby_cleanup(volatile int ex) { int state; ộ SAVE_ROOT_JMPBUF(th, ruby_finalize_0()); ộ ruby_finalize_1(); ộ return sysex; }
  17. eval.c /** Destructs the VM. * * Runs the VM

    finalization processes as well as ruby_finalize(), and * resources used by the VM. * * @param ex Default value to the return value. * @return If an error occurred returns a non-zero. If otherwise, retur * given ex. * @note This function does not raise any exception. */ int ruby_cleanup(volatile int ex) { int state; ộ SAVE_ROOT_JMPBUF(th, ruby_finalize_0()); ộ ruby_finalize_1(); ộ return sysex; } ऴྃ࣌ͷϑοΫͷ࣮ߦ
  18. eval.c static void ruby_finalize_0(void) { EC_PUSH_TAG(GET_EC()); if (EC_EXEC_TAG() == TAG_NONE)

    { rb_trap_exit(); } EC_POP_TAG(); rb_exec_end_proc(); rb_clear_trace_func(); }
  19. eval.c static void ruby_finalize_0(void) { EC_PUSH_TAG(GET_EC()); if (EC_EXEC_TAG() == TAG_NONE)

    { rb_trap_exit(); } EC_POP_TAG(); rb_exec_end_proc(); rb_clear_trace_func(); }
  20. eval_jump.c void rb_exec_end_proc(void) { enum ruby_tag_type state; rb_execution_context_t * volatile

    ec = GET_EC(); volatile VALUE errinfo = ec->errinfo; EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { again: exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo); exec_end_procs_chain(&end_procs, &ec->errinfo); } else { EC_TMPPOP_TAG(); error_handle(state); if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo; EC_REPUSH_TAG(); goto again;
  21. eval_jump.c void rb_exec_end_proc(void) { enum ruby_tag_type state; rb_execution_context_t * volatile

    ec = GET_EC(); volatile VALUE errinfo = ec->errinfo; EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { again: exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo); exec_end_procs_chain(&end_procs, &ec->errinfo); } else { EC_TMPPOP_TAG(); error_handle(state); if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo; EC_REPUSH_TAG(); goto again; BU@FYJUͰొ࿥ͨ͠
 ϒϩοΫΛ࣮ߦ
  22. eval_jump.c static void exec_end_procs_chain(struct end_proc_data *volatile *procs, VALUE *errp) {

    struct end_proc_data volatile endproc; struct end_proc_data *link; VALUE errinfo = *errp; while ((link = *procs) != 0) { *procs = link->next; endproc = *link; xfree(link); (*endproc.func) (endproc.data); *errp = errinfo; } }
  23. eval_jump.c static void exec_end_procs_chain(struct end_proc_data *volatile *procs, VALUE *errp) {

    struct end_proc_data volatile endproc; struct end_proc_data *link; VALUE errinfo = *errp; while ((link = *procs) != 0) { *procs = link->next; endproc = *link; xfree(link); (*endproc.func) (endproc.data); *errp = errinfo; } } ϦετΛઌ಄͔Βॱ൪ʹ࣮ߦ
 ʢat_exitΛݺͼग़ͨ͠ͷͱٯॱʹ࣮ߦʣ
  24. process.c VALUE rb_f_exit(int argc, const VALUE *argv) { int istatus;

    if (rb_check_arity(argc, 0, 1) == 1) { istatus = exit_status_code(argv[0]); } else { istatus = EXIT_SUCCESS; } rb_exit(istatus); UNREACHABLE_RETURN(Qnil); }
 
 rb_define_global_function("exit", rb_f_exit, -1);
  25. process.c VALUE rb_f_exit(int argc, const VALUE *argv) { int istatus;

    if (rb_check_arity(argc, 0, 1) == 1) { istatus = exit_status_code(argv[0]); } else { istatus = EXIT_SUCCESS; } rb_exit(istatus); UNREACHABLE_RETURN(Qnil); }
 
 rb_define_global_function("exit", rb_f_exit, -1); Kernel.exitͷఆٛ
  26. process.c VALUE rb_f_exit(int argc, const VALUE *argv) { int istatus;

    if (rb_check_arity(argc, 0, 1) == 1) { istatus = exit_status_code(argv[0]); } else { istatus = EXIT_SUCCESS; } rb_exit(istatus); UNREACHABLE_RETURN(Qnil); }
 
 rb_define_global_function("exit", rb_f_exit, -1); ॲཧͷதஅ
  27. process.c void rb_exit(int status) { if (GET_EC()->tag) { VALUE args[2];

    args[0] = INT2NUM(status); args[1] = rb_str_new2("exit"); rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); } ruby_stop(status); }
  28. process.c void rb_exit(int status) { if (GET_EC()->tag) { VALUE args[2];

    args[0] = INT2NUM(status); args[1] = rb_str_new2("exit"); rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); } ruby_stop(status); }
  29. eval.c /*! Calls ruby_cleanup() and exits the process */ void

    ruby_stop(int ex) { exit(ruby_cleanup(ex)); }
  30. eval.c /*! Calls ruby_cleanup() and exits the process */ void

    ruby_stop(int ex) { exit(ruby_cleanup(ex)); } ͖ͬ͞ݟͨ