ruby-changes:37288
From: nagachika <ko1@a...>
Date: Thu, 22 Jan 2015 01:10:12 +0900 (JST)
Subject: [ruby-changes:37288] nagachika:r49369 (ruby_2_1): merge revision(s) r48744, r48752: [Backport #10579]
nagachika 2015-01-22 01:09:59 +0900 (Thu, 22 Jan 2015) New Revision: 49369 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=49369 Log: 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] Modified directories: branches/ruby_2_1/ Modified files: branches/ruby_2_1/ChangeLog branches/ruby_2_1/eval.c branches/ruby_2_1/test/ruby/test_objectspace.rb branches/ruby_2_1/thread.c branches/ruby_2_1/version.h Index: ruby_2_1/ChangeLog =================================================================== --- ruby_2_1/ChangeLog (revision 49368) +++ ruby_2_1/ChangeLog (revision 49369) @@ -1,3 +1,19 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ChangeLog#L1 +Thu Jan 22 01:02:16 2015 Nobuyoshi Nakada <nobu@r...> + + * 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] + +Thu Jan 22 01:02:16 2015 Nobuyoshi Nakada <nobu@r...> + + * 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] + Thu Jan 22 00:54:00 2015 Nobuyoshi Nakada <nobu@r...> * parse.y (symbol_list): fix the node type of literal symbol list Index: ruby_2_1/thread.c =================================================================== --- ruby_2_1/thread.c (revision 49368) +++ ruby_2_1/thread.c (revision 49369) @@ -4763,6 +4763,8 @@ ident_hash_new(void) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L4763 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) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L4772 */ 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, VA https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L4876 * 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 https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L4926 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, VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L4952 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, VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L4966 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); } } Index: ruby_2_1/eval.c =================================================================== --- ruby_2_1/eval.c (revision 49368) +++ ruby_2_1/eval.c (revision 49369) @@ -978,6 +978,19 @@ prev_frame_func(void) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/eval.c#L978 return frame_func_id(prev_cfp); } +ID +rb_frame_last_func(void) +{ + rb_thread_t *th = GET_THREAD(); + rb_control_frame_t *cfp = th->cfp; + ID mid; + + while (!(mid = frame_func_id(cfp)) && + (cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp), + !RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp))); + return mid; +} + /* * call-seq: * append_features(mod) -> mod Index: ruby_2_1/version.h =================================================================== --- ruby_2_1/version.h (revision 49368) +++ ruby_2_1/version.h (revision 49369) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/version.h#L1 #define RUBY_VERSION "2.1.5" #define RUBY_RELEASE_DATE "2015-01-22" -#define RUBY_PATCHLEVEL 282 +#define RUBY_PATCHLEVEL 283 #define RUBY_RELEASE_YEAR 2015 #define RUBY_RELEASE_MONTH 1 Index: ruby_2_1/test/ruby/test_objectspace.rb =================================================================== --- ruby_2_1/test/ruby/test_objectspace.rb (revision 49368) +++ ruby_2_1/test/ruby/test_objectspace.rb (revision 49369) @@ -98,4 +98,11 @@ End https://github.com/ruby/ruby/blob/trunk/ruby_2_1/test/ruby/test_objectspace.rb#L98 } End end + + def test_each_object_recursive_key + assert_normal_exit(<<-'end;', '[ruby-core:66742] [Bug #10579]') + h = {["foo"]=>nil} + p Thread.current[:__recursive_key__] + end; + end end Property changes on: ruby_2_1 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r48744,48752 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/