From 74cb1bf1951d33de032efbc10cd4f37d20bd20b3 Mon Sep 17 00:00:00 2001 From: Watson Date: Tue, 12 Jun 2012 20:15:12 +0900 Subject: [PATCH] remove the object from recursive_objects in RoxorVM::exec_recursive() even if called function raises an exception --- vm.cpp | 26 +++++++++++++++++++------- vm.h | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/vm.cpp b/vm.cpp index f9f86208e..d0db41c76 100644 --- a/vm.cpp +++ b/vm.cpp @@ -4717,6 +4717,15 @@ rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg) return GET_VM()->exec_recursive(func, obj, arg); } +void +RoxorVM::remove_recursive_object(VALUE obj) +{ + std::vector::iterator iter = + std::find(recursive_objects.begin(), recursive_objects.end(), obj); + assert(iter != recursive_objects.end()); + recursive_objects.erase(iter); +} + VALUE RoxorVM::exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg) @@ -4729,13 +4738,16 @@ RoxorVM::exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, } recursive_objects.push_back(obj); - // XXX the function is not supposed to raise an exception. - VALUE ret = (*func) (obj, arg, Qfalse); - - iter = std::find(recursive_objects.begin(), recursive_objects.end(), obj); - assert(iter != recursive_objects.end()); - recursive_objects.erase(iter); - + VALUE ret; + try { + ret = (*func) (obj, arg, Qfalse); + } + catch (...) { + RoxorSpecialException *exc = get_special_exc(); + remove_recursive_object(obj); + throw exc; + } + remove_recursive_object(obj); return ret; } diff --git a/vm.h b/vm.h index 6127eead9..a227acdc6 100644 --- a/vm.h +++ b/vm.h @@ -1226,6 +1226,7 @@ class RoxorVM { void setup_from_current_thread(void); + void remove_recursive_object(VALUE obj); VALUE exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg);