summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval_intern.h8
-rw-r--r--eval_jump.c64
2 files changed, 34 insertions, 38 deletions
diff --git a/eval_intern.h b/eval_intern.h
index e32eafe2a8..5802e277ee 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -104,6 +104,12 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval
#define TH_POP_TAG2() \
_th->tag = _tag.prev
+#define TH_PUSH_TAG2() (_th->tag = &_tag, 0)
+
+#define TH_TMPPOP_TAG() TH_POP_TAG2()
+
+#define TH_REPUSH_TAG() TH_PUSH_TAG2()
+
#define PUSH_TAG() TH_PUSH_TAG(GET_THREAD())
#define POP_TAG() TH_POP_TAG()
@@ -128,7 +134,7 @@ rb_threadptr_tag_jump(rb_thread_t *th, int st)
[ISO/IEC 9899:1999] 7.13.1.1
*/
#define TH_EXEC_TAG() \
- (ruby_setjmp(_tag.buf) ? rb_threadptr_tag_state(_th) : (_th->tag = &_tag, 0))
+ (ruby_setjmp(_tag.buf) ? rb_threadptr_tag_state(_th) : TH_PUSH_TAG2())
#define EXEC_TAG() \
TH_EXEC_TAG()
diff --git a/eval_jump.c b/eval_jump.c
index 24bf2a2286..30094e9176 100644
--- a/eval_jump.c
+++ b/eval_jump.c
@@ -93,53 +93,43 @@ rb_mark_end_proc(void)
}
}
+static void
+exec_end_procs_chain(struct end_proc_data *volatile *procs)
+{
+ struct end_proc_data volatile endproc;
+ struct end_proc_data *link;
+
+ while ((link = *procs) != 0) {
+ *procs = link->next;
+ endproc = *link;
+ xfree(link);
+ rb_set_safe_level_force(endproc.safe);
+ (*endproc.func) (endproc.data);
+ }
+}
+
void
rb_exec_end_proc(void)
{
- struct end_proc_data volatile endproc;
- struct end_proc_data volatile *link;
int status;
volatile int safe = rb_safe_level();
rb_thread_t *th = GET_THREAD();
volatile VALUE errinfo = th->errinfo;
- while (ephemeral_end_procs) {
- link = ephemeral_end_procs;
- ephemeral_end_procs = link->next;
- endproc = *link;
- xfree((void *)link);
- link = &endproc;
-
- 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);
- if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
- }
+ PUSH_TAG();
+ if ((status = EXEC_TAG()) == 0) {
+ again:
+ exec_end_procs_chain(&ephemeral_end_procs);
+ exec_end_procs_chain(&end_procs);
}
-
- while (end_procs) {
- link = end_procs;
- end_procs = link->next;
- endproc = *link;
- xfree((void *)link);
- link = &endproc;
-
- 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);
- if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
- }
+ else {
+ TH_TMPPOP_TAG();
+ error_handle(status);
+ if (!NIL_P(th->errinfo)) errinfo = th->errinfo;
+ TH_REPUSH_TAG();
+ goto again;
}
+ POP_TAG();
rb_set_safe_level_force(safe);
th->errinfo = errinfo;