6 #include "eval_intern.h"
11 rb_call_end_proc(VALUE data
)
13 rb_proc_call(data
, rb_ary_new());
18 * at_exit { block } -> proc
20 * Converts _block_ to a +Proc+ object (and therefore
21 * binds it at the point of call) and registers it for execution when
22 * the program exits. If multiple handlers are registered, they are
23 * executed in reverse order of registration.
25 * def do_at_exit(str1)
26 * at_exit { print str1 }
28 * at_exit { puts "cruel world" }
29 * do_at_exit("goodbye ")
42 if (!rb_block_given_p()) {
43 rb_raise(rb_eArgError
, "called without a block");
45 proc
= rb_block_proc();
46 rb_set_end_proc(rb_call_end_proc
, proc
);
50 struct end_proc_data
{
53 struct end_proc_data
*next
;
56 static struct end_proc_data
*end_procs
, *ephemeral_end_procs
;
59 rb_set_end_proc(void (*func
)(VALUE
), VALUE data
)
61 struct end_proc_data
*link
= ALLOC(struct end_proc_data
);
62 struct end_proc_data
**list
;
63 rb_thread_t
*th
= GET_THREAD();
65 if (th
->top_wrapper
) {
66 list
= &ephemeral_end_procs
;
78 rb_mark_end_proc(void)
80 struct end_proc_data
*link
;
84 rb_gc_mark(link
->data
);
87 link
= ephemeral_end_procs
;
89 rb_gc_mark(link
->data
);
95 exec_end_procs_chain(struct end_proc_data
*volatile *procs
, VALUE
*errp
)
97 struct end_proc_data
volatile endproc
;
98 struct end_proc_data
*link
;
99 VALUE errinfo
= *errp
;
101 while ((link
= *procs
) != 0) {
105 (*endproc
.func
) (endproc
.data
);
111 rb_ec_exec_end_proc(rb_execution_context_t
* ec
)
113 enum ruby_tag_type state
;
114 volatile VALUE errinfo
= ec
->errinfo
;
117 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
119 exec_end_procs_chain(&ephemeral_end_procs
, &ec
->errinfo
);
120 exec_end_procs_chain(&end_procs
, &ec
->errinfo
);
124 error_handle(ec
, state
);
125 if (!NIL_P(ec
->errinfo
)) errinfo
= ec
->errinfo
;
131 ec
->errinfo
= errinfo
;
137 rb_define_global_function("at_exit", rb_f_at_exit
, 0);