From 98932f5150c2e6e26976c9e20b34d79c645e6593 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 8 Feb 2013 07:09:48 +0000 Subject: [PATCH] eval.c: preserve errinfo * eval.c (rb_ensure): preserve errinfo accross ensure proc before JUMP_TAG(). [ruby-core:52022] [Bug #7802] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39156 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ eval.c | 4 ++++ ext/-test-/exception/ensured.c | 25 ++++++++++++++++++++++ test/-ext-/exception/test_ensured.rb | 32 ++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 ext/-test-/exception/ensured.c create mode 100644 test/-ext-/exception/test_ensured.rb diff --git a/ChangeLog b/ChangeLog index e88ab65b1821ab..c6f1dbde8540ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri Feb 8 16:09:45 2013 Nobuyoshi Nakada + + * 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 * test/ruby/envutil.rb (assert_separately): check also terminating diff --git a/eval.c b/eval.c index c4bda485249aed..958daa8752d1d6 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 00000000000000..365e1f4f7980c0 --- /dev/null +++ b/ext/-test-/exception/ensured.c @@ -0,0 +1,25 @@ +#include + +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 00000000000000..103250c678a3a0 --- /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