mrb_open: return mrb_state with exc set on init failure

changed mrb_open() and mrb_open_core() to return mrb_state with mrb->exc
set (instead of NULL) when initialization fails. this allows callers to
programmatically inspect error details, which is essential for embedded
systems without stderr. return NULL only for true allocation failure.

added MRB_OPEN_SUCCESS(mrb) macro to check initialization success, since
mrb != NULL no longer guarantees success. updated all binary tools
(mruby, mirb, mrdb, mrbtest) to use new pattern: check MRB_OPEN_SUCCESS,
print exception details via mrb_print_error if available, then mrb_close.

mrb_core_init_protect now preserves exception in mrb->exc instead of
printing and clearing it, giving caller control over error handling.

breaking change: callers must use MRB_OPEN_SUCCESS(mrb) or check both
mrb != NULL && mrb->exc == NULL. old NULL-only checks will miss
initialization failures.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-11-13 19:10:46 +09:00
parent 92640097ab
commit 05ffe0c441
7 changed files with 71 additions and 21 deletions
+1 -7
View File
@@ -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;
+7 -6
View File
@@ -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