summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-01-21 16:09:59 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-01-21 16:09:59 +0000
commit4b0a168d7b82d7b9e50f61fe8d7a336dc8d84316 (patch)
tree9161530dc3e6a44a168286bfd8165682f49c491c /thread.c
parent83c5b533e36761141ed4dbd9db28e74520cb0ffd (diff)
merge revision(s) r48744,r48752: [Backport #10579]
* eval.c (rb_frame_last_func): return the most recent frame method name. * thread.c (recursive_list_access): use the last method name, instead of the current method name which can be unset in some cases, not to use a symbol by the invalid ID. [ruby-core:66742] [Bug #10579] * thread.c (exec_recursive): use the same last method name as recursive_push in the error message when recursive_pop failed. [ruby-core:66742] [Bug #10579] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@49369 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/thread.c b/thread.c
index d9df90272e..b24d29e087 100644
--- a/thread.c
+++ b/thread.c
@@ -4763,6 +4763,8 @@ ident_hash_new(void)
return hash;
}
+ID rb_frame_last_func(void);
+
/*
* Returns the current "recursive list" used to detect recursion.
* This list is a hash table, unique for the current thread and for
@@ -4770,10 +4772,9 @@ ident_hash_new(void)
*/
static VALUE
-recursive_list_access(void)
+recursive_list_access(VALUE sym)
{
volatile VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
- VALUE sym = ID2SYM(rb_frame_this_func());
VALUE list;
if (NIL_P(hash) || !RB_TYPE_P(hash, T_HASH)) {
hash = ident_hash_new();
@@ -4875,25 +4876,23 @@ recursive_push(VALUE list, VALUE obj, VALUE paired_obj)
* Assumes the recursion list is valid.
*/
-static void
+static int
recursive_pop(VALUE list, VALUE obj, VALUE paired_obj)
{
if (paired_obj) {
VALUE pair_list = rb_hash_lookup2(list, obj, Qundef);
if (pair_list == Qundef) {
- VALUE symname = rb_inspect(ID2SYM(rb_frame_this_func()));
- VALUE thrname = rb_inspect(rb_thread_current());
- rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list for %s in %s",
- StringValuePtr(symname), StringValuePtr(thrname));
+ return 0;
}
if (RB_TYPE_P(pair_list, T_HASH)) {
rb_hash_delete(pair_list, paired_obj);
if (!RHASH_EMPTY_P(pair_list)) {
- return; /* keep hash until is empty */
+ return 1; /* keep hash until is empty */
}
}
}
rb_hash_delete(list, obj);
+ return 1;
}
struct exec_recursive_params {
@@ -4927,9 +4926,11 @@ static VALUE
exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE arg, int outer)
{
VALUE result = Qundef;
+ const ID mid = rb_frame_last_func();
+ const VALUE sym = mid ? ID2SYM(mid) : ID2SYM(idNULL);
struct exec_recursive_params p;
int outermost;
- p.list = recursive_list_access();
+ p.list = recursive_list_access(sym);
p.objid = rb_obj_id(obj);
p.obj = obj;
p.pairid = pairid;
@@ -4951,8 +4952,8 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE
recursive_push(p.list, ID2SYM(recursive_key), 0);
recursive_push(p.list, p.objid, p.pairid);
result = rb_catch_protect(p.list, exec_recursive_i, (VALUE)&p, &state);
- recursive_pop(p.list, p.objid, p.pairid);
- recursive_pop(p.list, ID2SYM(recursive_key), 0);
+ if (!recursive_pop(p.list, p.objid, p.pairid)) goto invalid;
+ if (!recursive_pop(p.list, ID2SYM(recursive_key), 0)) goto invalid;
if (state) JUMP_TAG(state);
if (result == p.list) {
result = (*func)(obj, arg, TRUE);
@@ -4965,7 +4966,12 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE
result = (*func)(obj, arg, FALSE);
}
POP_TAG();
- recursive_pop(p.list, p.objid, p.pairid);
+ if (!recursive_pop(p.list, p.objid, p.pairid)) {
+ invalid:
+ rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list "
+ "for %+"PRIsVALUE" in %+"PRIsVALUE,
+ sym, rb_thread_current());
+ }
if (state) JUMP_TAG(state);
}
}