diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-01-14 07:04:09 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-01-14 07:04:09 +0000 |
commit | 9120d051e14a69d3c1e439d65d85a4a8060d62fb (patch) | |
tree | 1263a58684cbdedf82ed343a11b7bae00f441881 | |
parent | e6a5f817d613dbd40cf2d19cd0705a1b4c377538 (diff) |
merge revision(s) 48744,48752: [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_0_0@49246 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | eval.c | 13 | ||||
-rw-r--r-- | test/ruby/test_objectspace.rb | 7 | ||||
-rw-r--r-- | thread.c | 23 | ||||
-rw-r--r-- | version.h | 2 |
5 files changed, 50 insertions, 11 deletions
@@ -1,3 +1,19 @@ +Wed Jan 14 15:57:26 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * 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] + +Wed Jan 14 15:57:26 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * 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] + Wed Jan 14 15:54:18 2015 Aaron Patterson <aaron@tenderlovemaking.com> * lib/resolv.rb: fall back if canonicalization fails. @@ -931,6 +931,19 @@ rb_frame_caller(void) 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 diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index 3127b61abe..16fe004a2a 100644 --- a/test/ruby/test_objectspace.rb +++ b/test/ruby/test_objectspace.rb @@ -84,4 +84,11 @@ End } 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 @@ -4675,10 +4675,9 @@ static ID recursive_key; */ 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 = rb_hash_new(); @@ -4769,25 +4768,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 { @@ -4832,9 +4829,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; @@ -4853,7 +4852,11 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE if (outermost) { recursive_push(p.list, ID2SYM(recursive_key), 0); result = rb_catch_obj(p.list, exec_recursive_i, (VALUE)&p); - recursive_pop(p.list, ID2SYM(recursive_key), 0); + if (!recursive_pop(p.list, ID2SYM(recursive_key), 0)) { + rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list " + "for %+"PRIsVALUE" in %+"PRIsVALUE, + sym, rb_thread_current()); + } if (result == p.list) { result = (*func)(obj, arg, TRUE); } @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.0.0" #define RUBY_RELEASE_DATE "2015-01-14" -#define RUBY_PATCHLEVEL 607 +#define RUBY_PATCHLEVEL 608 #define RUBY_RELEASE_YEAR 2015 #define RUBY_RELEASE_MONTH 1 |