diff --git a/common.mk b/common.mk index ff56a0c93f..236d40ed04 100644 --- a/common.mk +++ b/common.mk @@ -1942,6 +1942,7 @@ error.$(OBJEXT): $(CCAN_DIR)/list/list.h error.$(OBJEXT): $(CCAN_DIR)/str/str.h error.$(OBJEXT): $(hdrdir)/ruby.h error.$(OBJEXT): $(hdrdir)/ruby/ruby.h +error.$(OBJEXT): $(hdrdir)/ruby/thread.h error.$(OBJEXT): {$(VPATH)}assert.h error.$(OBJEXT): {$(VPATH)}config.h error.$(OBJEXT): {$(VPATH)}defines.h diff --git a/error.c b/error.c index e29910ae92..3a63a5f2a9 100644 --- a/error.c +++ b/error.c @@ -11,6 +11,7 @@ #include "ruby/encoding.h" #include "ruby/st.h" +#include "ruby/thread.h" #include "internal.h" #include "ruby_assert.h" #include "vm_core.h" @@ -2604,16 +2605,46 @@ rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) rb_exc_raise(rb_exc_new3(exc, mesg)); } +struct rb_raise_tag { + VALUE exc; + const char *fmt; + va_list *args; +}; + +static void * +rb_vraise(void *ptr) +{ + struct rb_raise_tag *argv = ptr; + VALUE msg = rb_vsprintf(argv->fmt, *argv->args); + VALUE exc = rb_exc_new3(argv->exc, msg); + rb_exc_raise(exc); + UNREACHABLE_RETURN(NULL); +} + void rb_raise(VALUE exc, const char *fmt, ...) { va_list args; - VALUE mesg; - va_start(args, fmt); - mesg = rb_vsprintf(fmt, args); + struct rb_raise_tag argv = { + exc, fmt, &args, + }; + + if (ruby_thread_has_gvl_p()) { + rb_vraise(&argv); + UNREACHABLE; + } + else if (ruby_native_thread_p()) { + rb_thread_call_with_gvl(rb_vraise, &argv); + UNREACHABLE; + } + else { + /* Not in a ruby thread */ + vfprintf(stderr, fmt, args); + abort(); + } + va_end(args); - rb_exc_raise(rb_exc_new3(exc, mesg)); } NORETURN(static void raise_loaderror(VALUE path, VALUE mesg)); diff --git a/gc.c b/gc.c index f4292370a0..cc4ea12250 100644 --- a/gc.c +++ b/gc.c @@ -172,6 +172,9 @@ size_mul_or_raise(size_t x, size_t y, VALUE exc) if (LIKELY(!t.left)) { return t.right; } + else if (rb_during_gc()) { + rb_memerror(); /* or...? */ + } else { rb_raise( exc, @@ -195,6 +198,9 @@ size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc) if (LIKELY(!t.left)) { return t.right; } + else if (rb_during_gc()) { + rb_memerror(); /* or...? */ + } else { rb_raise( exc, @@ -219,6 +225,9 @@ size_mul_add_mul_or_raise(size_t x, size_t y, size_t z, size_t w, VALUE exc) if (LIKELY(!t.left)) { return t.right; } + else if (rb_during_gc()) { + rb_memerror(); /* or...? */ + } else { rb_raise( exc, @@ -9590,28 +9599,10 @@ objspace_reachable_objects_from_root(rb_objspace_t *objspace, void (func)(const static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size); -static void * -negative_size_allocation_error_with_gvl(void *ptr) -{ - rb_raise(rb_eNoMemError, "%s", (const char *)ptr); - return 0; /* should not be reached */ -} - static void negative_size_allocation_error(const char *msg) { - if (ruby_thread_has_gvl_p()) { - rb_raise(rb_eNoMemError, "%s", msg); - } - else { - if (ruby_native_thread_p()) { - rb_thread_call_with_gvl(negative_size_allocation_error_with_gvl, (void *)msg); - } - else { - fprintf(stderr, "[FATAL] %s\n", msg); - exit(EXIT_FAILURE); - } - } + rb_raise(rb_eNoMemError, "%s", msg); } static void *