diff options
Diffstat (limited to 'error.c')
-rw-r--r-- | error.c | 39 |
1 files changed, 35 insertions, 4 deletions
@@ -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)); |