summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--eval.c4
-rw-r--r--ext/-test-/exception/ensured.c25
-rw-r--r--test/-ext-/exception/test_ensured.rb32
4 files changed, 66 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index e88ab65b18..c6f1dbde85 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Feb 8 16:09:45 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_ensure): preserve errinfo accross ensure proc before
+ JUMP_TAG(). [ruby-core:52022] [Bug #7802]
+
Fri Feb 8 16:08:28 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/ruby/envutil.rb (assert_separately): check also terminating
diff --git a/eval.c b/eval.c
index c4bda48524..958daa8752 100644
--- a/eval.c
+++ b/eval.c
@@ -805,6 +805,8 @@ rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE
{
int state;
volatile VALUE result = Qnil;
+ volatile VALUE errinfo;
+ rb_thread_t *const th = GET_THREAD();
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
@@ -813,7 +815,9 @@ rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE
POP_TAG();
/* TODO: fix me */
/* retval = prot_tag ? prot_tag->retval : Qnil; */ /* save retval */
+ errinfo = th->errinfo;
(*e_proc) (data2);
+ th->errinfo = errinfo;
if (state)
JUMP_TAG(state);
return result;
diff --git a/ext/-test-/exception/ensured.c b/ext/-test-/exception/ensured.c
new file mode 100644
index 0000000000..365e1f4f79
--- /dev/null
+++ b/ext/-test-/exception/ensured.c
@@ -0,0 +1,25 @@
+#include <ruby.h>
+
+static VALUE
+begin(VALUE object)
+{
+ return rb_funcall(object, rb_intern("try_method"), 0);
+}
+
+static VALUE
+ensure(VALUE object)
+{
+ return rb_funcall(object, rb_intern("ensured_method"), 0);
+}
+
+static VALUE
+ensured(VALUE module, VALUE object)
+{
+ return rb_ensure(begin, object, ensure, object);
+}
+
+void
+Init_ensured(VALUE klass)
+{
+ rb_define_module_function(klass, "ensured", ensured, 1);
+}
diff --git a/test/-ext-/exception/test_ensured.rb b/test/-ext-/exception/test_ensured.rb
new file mode 100644
index 0000000000..103250c678
--- /dev/null
+++ b/test/-ext-/exception/test_ensured.rb
@@ -0,0 +1,32 @@
+require 'test/unit'
+require_relative '../../ruby/envutil'
+
+module Bug
+ class Bug7802 < RuntimeError
+ end
+
+ class TestException < Test::Unit::TestCase
+ def test_ensured
+ assert_separately([], <<-'end;') # do
+
+ require '-test-/exception'
+
+ module Bug
+ class Bug7802 < RuntimeError
+ def try_method
+ raise self
+ end
+
+ def ensured_method
+ [1].detect {|i| true}
+ end
+ end
+ end
+
+ assert_raise(Bug::Bug7802, '[ruby-core:52022] [Bug #7802]') {
+ Bug::Exception.ensured(Bug::Bug7802.new)
+ }
+ end;
+ end
+ end
+end