diff options
Diffstat (limited to 'eval_jump.c')
| -rw-r--r-- | eval_jump.c | 104 |
1 files changed, 45 insertions, 59 deletions
diff --git a/eval_jump.c b/eval_jump.c index 18b6835c9c..6ee8ff4a6f 100644 --- a/eval_jump.c +++ b/eval_jump.c @@ -35,12 +35,12 @@ rb_call_end_proc(VALUE data) */ static VALUE -rb_f_at_exit(void) +rb_f_at_exit(VALUE _) { VALUE proc; if (!rb_block_given_p()) { - rb_raise(rb_eArgError, "called without a block"); + rb_raise(rb_eArgError, "called without a block"); } proc = rb_block_proc(); rb_set_end_proc(rb_call_end_proc, proc); @@ -48,13 +48,12 @@ rb_f_at_exit(void) } struct end_proc_data { - void (*func) (); + void (*func) (VALUE); VALUE data; - int safe; struct end_proc_data *next; }; -static struct end_proc_data *end_procs, *ephemeral_end_procs, *tmp_end_procs; +static struct end_proc_data *end_procs, *ephemeral_end_procs; void rb_set_end_proc(void (*func)(VALUE), VALUE data) @@ -64,15 +63,14 @@ rb_set_end_proc(void (*func)(VALUE), VALUE data) rb_thread_t *th = GET_THREAD(); if (th->top_wrapper) { - list = &ephemeral_end_procs; + list = &ephemeral_end_procs; } else { - list = &end_procs; + list = &end_procs; } link->next = *list; link->func = func; link->data = data; - link->safe = rb_safe_level(); *list = link; } @@ -83,66 +81,54 @@ rb_mark_end_proc(void) link = end_procs; while (link) { - rb_gc_mark(link->data); - link = link->next; + rb_gc_mark(link->data); + link = link->next; } link = ephemeral_end_procs; while (link) { - rb_gc_mark(link->data); - link = link->next; - } - link = tmp_end_procs; - while (link) { - rb_gc_mark(link->data); - link = link->next; + rb_gc_mark(link->data); + link = link->next; } } -void -rb_exec_end_proc(void) +static void +exec_end_procs_chain(struct end_proc_data *volatile *procs, VALUE *errp) { - struct end_proc_data *volatile link; - struct end_proc_data *tmp; - int status; - volatile int safe = rb_safe_level(); - - while (ephemeral_end_procs) { - tmp_end_procs = link = ephemeral_end_procs; - ephemeral_end_procs = 0; - while (link) { - PUSH_TAG(); - if ((status = EXEC_TAG()) == 0) { - rb_set_safe_level_force(link->safe); - (*link->func) (link->data); - } - POP_TAG(); - if (status) { - error_handle(status); - } - tmp = link; - tmp_end_procs = link = link->next; - xfree(tmp); - } + struct end_proc_data volatile endproc; + struct end_proc_data *link; + VALUE errinfo = *errp; + + while ((link = *procs) != 0) { + *procs = link->next; + endproc = *link; + SIZED_FREE(link); + (*endproc.func) (endproc.data); + *errp = errinfo; } - while (end_procs) { - tmp_end_procs = link = end_procs; - end_procs = 0; - while (link) { - PUSH_TAG(); - if ((status = EXEC_TAG()) == 0) { - rb_set_safe_level_force(link->safe); - (*link->func) (link->data); - } - POP_TAG(); - if (status) { - error_handle(status); - } - tmp = link; - tmp_end_procs = link = link->next; - xfree(tmp); - } +} + +static void +rb_ec_exec_end_proc(rb_execution_context_t * ec) +{ + enum ruby_tag_type state; + volatile VALUE errinfo = ec->errinfo; + volatile bool finished = false; + + while (!finished) { + EC_PUSH_TAG(ec); + if ((state = EC_EXEC_TAG()) == TAG_NONE) { + exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo); + exec_end_procs_chain(&end_procs, &ec->errinfo); + finished = true; + } + EC_POP_TAG(); + if (state != TAG_NONE) { + error_handle(ec, ec->errinfo, state); + if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo; + } } - rb_set_safe_level_force(safe); + + ec->errinfo = errinfo; } void |
