aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c35
-rw-r--r--test/ruby/test_exception.rb17
2 files changed, 45 insertions, 7 deletions
diff --git a/eval.c b/eval.c
index a398479fb2..5b67e1a003 100644
--- a/eval.c
+++ b/eval.c
@@ -431,6 +431,34 @@ rb_frozen_class_p(VALUE klass)
}
NORETURN(static void rb_longjmp(int, volatile VALUE));
+static VALUE get_errinfo(void);
+static VALUE get_thread_errinfo(rb_thread_t *th);
+
+static VALUE
+exc_setup_cause(VALUE exc, VALUE cause)
+{
+ ID id_cause;
+ CONST_ID(id_cause, "cause");
+
+#if SUPPORT_JOKE
+ if (NIL_P(cause)) {
+ ID id_true_cause;
+ CONST_ID(id_true_cause, "true_cause");
+
+ cause = rb_attr_get(rb_eFatal, id_true_cause);
+ if (NIL_P(cause)) {
+ cause = rb_exc_new_cstr(rb_eFatal, "because using such Ruby");
+ rb_ivar_set(cause, id_cause, INT2FIX(42)); /* the answer */
+ OBJ_FREEZE(cause);
+ rb_ivar_set(rb_eFatal, id_true_cause, cause);
+ }
+ }
+#endif
+ if (!NIL_P(cause) && cause != exc) {
+ rb_ivar_set(exc, id_cause, cause);
+ }
+ return exc;
+}
static void
setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
@@ -447,6 +475,7 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg)
if (NIL_P(mesg)) {
mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
}
+ exc_setup_cause(mesg, get_thread_errinfo(th));
file = rb_sourcefile();
if (file) line = rb_sourceline();
@@ -552,8 +581,6 @@ rb_interrupt(void)
rb_raise(rb_eInterrupt, "%s", "");
}
-static VALUE get_errinfo(void);
-
/*
* call-seq:
* raise
@@ -641,10 +668,6 @@ make_exception(int argc, VALUE *argv, int isstr)
if (argc > 2)
set_backtrace(mesg, argv[2]);
}
- {
- VALUE cause = get_errinfo();
- if (!NIL_P(cause)) rb_iv_set(mesg, "cause", cause);
- }
return mesg;
}
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 32b87f2d92..92438ad742 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -479,16 +479,31 @@ end.join
def test_cause
msg = "[Feature #8257]"
+ cause = nil
e = assert_raise(StandardError) {
begin
raise msg
rescue => e
- assert_nil(e.cause, msg)
+ cause = e.cause
raise StandardError
end
}
+ assert_nil(cause, msg)
cause = e.cause
assert_instance_of(RuntimeError, cause, msg)
assert_equal(msg, cause.message, msg)
end
+
+ def test_cause_reraised
+ msg = "[Feature #8257]"
+ cause = nil
+ e = assert_raise(RuntimeError) {
+ begin
+ raise msg
+ rescue => e
+ raise e
+ end
+ }
+ assert_not_same(e, e.cause, "#{msg}: should not be recursive")
+ end
end