diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-09-29 10:21:10 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-10-12 18:20:29 +0900 |
| commit | 3d6adccfbec44fb13a75ef7055f10fb87242d1fc (patch) | |
| tree | 046e3941a84587f2407d32317afeaff2e9f2aa20 | |
| parent | 5069fb15e41998dffef8e0ba566b3a82be369ba3 (diff) | |
| download | mruby-3d6adccfbec44fb13a75ef7055f10fb87242d1fc.tar.gz mruby-3d6adccfbec44fb13a75ef7055f10fb87242d1fc.zip | |
Add a new function `mrb_exc_protect()`.
`mrb_exc_protect()` takes two C functions, `body` to be executed first,
and `resc` to be executed when an error happens during `body` execution.
Since `mrb_exc_protect()` should be compiled with the proper compiler,
we will not see the problem like #5088 that was caused by `setjmp()` and
`throw` mixture.
| -rw-r--r-- | include/mruby.h | 3 | ||||
| -rw-r--r-- | src/error.c | 23 |
2 files changed, 26 insertions, 0 deletions
diff --git a/include/mruby.h b/include/mruby.h index 52bcd58bf..4bbffb189 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1293,6 +1293,9 @@ MRB_API void mrb_print_backtrace(mrb_state *mrb); MRB_API void mrb_print_error(mrb_state *mrb); /* function for `raisef` formatting */ MRB_API mrb_value mrb_vformat(mrb_state *mrb, const char *format, va_list ap); +/* function to protect errors during execution */ +MRB_API mrb_value mrb_exc_protect(mrb_state *mrb, mrb_value (*body)(mrb_state*, void*), void *a, mrb_value (*resc)(mrb_state*, void*, mrb_value), void *b); + /* macros to get typical exception objects note: diff --git a/src/error.c b/src/error.c index b19f0ea43..c077c8663 100644 --- a/src/error.c +++ b/src/error.c @@ -555,6 +555,29 @@ mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max) #undef FMT } +MRB_API mrb_value +mrb_exc_protect(mrb_state *mrb, mrb_value (*body)(mrb_state*, void*), void *a, + mrb_value (*resc)(mrb_state*, void*, mrb_value), void *b) +{ + struct mrb_jmpbuf *prev_jmp = mrb->jmp; + struct mrb_jmpbuf c_jmp; + mrb_value v = mrb_undef_value(); + + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + v = body(mrb, a); + } MRB_CATCH(&c_jmp) { + if (mrb->exc) { + v = resc(mrb, b, mrb_obj_value(mrb->exc)); + mrb->exc = NULL; + } + } MRB_END_EXC(&c_jmp); + + mrb->jmp = prev_jmp; + + return v; +} + void mrb_core_init_printabort(void); int |
