aboutsummaryrefslogtreecommitdiffstats
path: root/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'error.c')
-rw-r--r--error.c39
1 files changed, 35 insertions, 4 deletions
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));