diff --git a/include/mruby.h b/include/mruby.h index 6331ca8c9..ee23688ff 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1270,6 +1270,29 @@ MRB_API mrb_state* mrb_open_core(void); MRB_API void mrb_close(mrb_state *mrb); MRB_API void mrb_method_cache_clear(mrb_state *mrb); +/** + * Check if mrb_open() succeeded + * + * @param mrb + * Pointer returned from mrb_open() or mrb_open_core(). + * @return + * Non-zero if initialization succeeded, 0 if failed. + * @note + * mrb_open() may return non-NULL even on failure (with mrb->exc set). + * Use this macro to check for success: + * @code + * mrb_state *mrb = mrb_open(); + * if (!MRB_OPEN_SUCCESS(mrb)) { + * if (mrb) { + * // Inspect mrb->exc for error details + * mrb_close(mrb); + * } + * return EXIT_FAILURE; + * } + * @endcode + */ +#define MRB_OPEN_SUCCESS(mrb) ((mrb) && !(mrb)->exc) + /** * The memory allocation function. You can redefine this function for your own allocator. * diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c index 0413c0be0..a135b0fa7 100644 --- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c @@ -673,8 +673,16 @@ main(int argc, char **argv) l_restart: - if (mrb == NULL) { - fputs("Invalid mrb_state, exiting mruby\n", stderr); + if (!MRB_OPEN_SUCCESS(mrb)) { + if (mrb) { + /* Initialization failed - print exception details */ + mrb_print_error(mrb); + mrb_close(mrb); + } + else { + /* Allocation failed */ + fputs("Failed to allocate mrb_state, exiting mrdb\n", stderr); + } return EXIT_FAILURE; } diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 2c003758e..77ab8ce6b 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -475,8 +475,16 @@ main(int argc, char **argv) /* new interpreter instance */ mrb = mrb_open(); - if (mrb == NULL) { - fputs("Invalid mrb interpreter, exiting mirb\n", stderr); + if (!MRB_OPEN_SUCCESS(mrb)) { + if (mrb) { + /* Initialization failed - print exception details */ + mrb_print_error(mrb); + mrb_close(mrb); + } + else { + /* Allocation failed */ + fputs("Failed to allocate mrb_state, exiting mirb\n", stderr); + } return EXIT_FAILURE; } diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c index 253410165..38274c399 100644 --- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c @@ -282,8 +282,16 @@ main(int argc, char **argv) mrb_value ARGV; mrb_value v; - if (mrb == NULL) { - fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv); + if (!MRB_OPEN_SUCCESS(mrb)) { + if (mrb) { + /* Initialization failed - print exception details */ + mrb_print_error(mrb); + mrb_close(mrb); + } + else { + /* Allocation failed */ + fprintf(stderr, "%s: Failed to allocate mrb_state, exiting mruby\n", *argv); + } return EXIT_FAILURE; } diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c index e62bc0147..d1decad8b 100644 --- a/mrbgems/mruby-test/driver.c +++ b/mrbgems/mruby-test/driver.c @@ -290,8 +290,16 @@ main(int argc, char **argv) /* new interpreter instance */ mrb = mrb_open(); - if (mrb == NULL) { - fputs("Invalid mrb_state, exiting test driver", stderr); + if (!MRB_OPEN_SUCCESS(mrb)) { + if (mrb) { + /* Initialization failed - print exception details */ + mrb_print_error(mrb); + mrb_close(mrb); + } + else { + /* Allocation failed */ + fputs("Failed to allocate mrb_state, exiting test driver", stderr); + } return EXIT_FAILURE; } diff --git a/src/error.c b/src/error.c index 4b39381dd..ffb9e4792 100644 --- a/src/error.c +++ b/src/error.c @@ -741,13 +741,7 @@ mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state*, void*), void *opa body(mrb, opaque); err = 0; } MRB_CATCH(&c_jmp) { - if (mrb->exc) { - mrb_print_error(mrb); - mrb->exc = NULL; - } - else { - mrb_core_init_printabort(mrb); - } + /* Leave mrb->exc set for caller to inspect */ } MRB_END_EXC(&c_jmp); mrb->jmp = prev_jmp; diff --git a/src/state.c b/src/state.c index 1b3d687b9..ee536901a 100644 --- a/src/state.c +++ b/src/state.c @@ -50,8 +50,8 @@ mrb_open_core(void) mrb->bootstrapping = TRUE; if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) { - mrb_close(mrb); - return NULL; + /* Return mrb with mrb->exc set for caller to inspect */ + return mrb; } mrb_method_cache_clear(mrb); @@ -74,14 +74,15 @@ mrb_open(void) { mrb_state *mrb = mrb_open_core(); - if (mrb == NULL) { - return NULL; + if (mrb == NULL || mrb->exc) { + /* Either allocation failed or core init failed */ + return mrb; } #ifndef MRB_NO_GEMS if (mrb_core_init_protect(mrb, init_mrbgems, NULL)) { - mrb_close(mrb); - return NULL; + /* Gem init failed - return mrb with mrb->exc set */ + return mrb; } mrb_gc_arena_restore(mrb, 0); #endif