From: usa@... Date: 2014-08-31T07:39:38+00:00 Subject: [ruby-dev:48505] [ruby-trunk - Bug #9957] TracePoint catch b_return at rescue/ensure Issue #9957 has been updated by Usaku NAKAMURA. Backport changed from 2.0.0: REQUIRED, 2.1: DONE to 2.0.0: DONE, 2.1: DONE backported into `ruby_2_0_0` at r47339. ---------------------------------------- Bug #9957: TracePoint catch b_return at rescue/ensure https://bugs.ruby-lang.org/issues/9957#change-48589 * Author: Koichi Sasada * Status: Closed * Priority: Normal * Assignee: Koichi Sasada * Category: core * Target version: current: 2.2.0 * ruby -v: 2.2 * Backport: 2.0.0: DONE, 2.1: DONE ---------------------------------------- TracePonit では b_return という、ブロックから出る時のイベントがあるのですが、rescue 節から大域脱出で抜けるとき、誤って b_return イベントを発生させていました。そのため、次のようなテストで失敗します。ブロックが無いのに b_return が発生してしまっています。 ```ruby def method_test_rescue_should_not_cause_b_return begin raise rescue return end end def method_test_ensure_should_not_cause_b_return begin raise ensure return end end def test_rescue_and_ensure_should_not_cause_b_return curr_thread = Thread.current trace = TracePoint.new(:b_call, :b_return){ next if curr_thread != Thread.current flunk("Should not reach here because there is no block.") } begin trace.enable method_test_rescue_should_not_cause_b_return begin method_test_ensure_should_not_cause_b_return rescue # ignore end ensure trace.disable end end ``` これは、フレームの構造をブロック呼び出しと同じようにしていたのが原因です。 次のパッチで修正できます。 ```diff Index: vm.c =================================================================== --- vm.c (revision 46458) +++ vm.c (working copy) @@ -1520,7 +1527,7 @@ /* push block frame */ cfp->sp[0] = err; - vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK, + vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_RESCUE, cfp->self, cfp->klass, VM_ENVVAL_PREV_EP_PTR(cfp->ep), catch_iseq->iseq_encoded, Index: vm_core.h =================================================================== --- vm_core.h (revision 46458) +++ vm_core.h (working copy) @@ -756,7 +756,8 @@ #define VM_FRAME_MAGIC_IFUNC 0x81 #define VM_FRAME_MAGIC_EVAL 0x91 #define VM_FRAME_MAGIC_LAMBDA 0xa1 -#define VM_FRAME_MAGIC_MASK_BITS 8 +#define VM_FRAME_MAGIC_RESCUE 0xb1 +#define VM_FRAME_MAGIC_MASK_BITS 8 #define VM_FRAME_MAGIC_MASK (~(~0<flag & VM_FRAME_MAGIC_MASK) Index: vm_dump.c =================================================================== --- vm_dump.c (revision 46458) +++ vm_dump.c (working copy) @@ -73,6 +73,9 @@ case VM_FRAME_MAGIC_EVAL: magic = "EVAL"; break; + case VM_FRAME_MAGIC_RESCUE: + magic = "RESCUE"; + break; case 0: magic = "------"; break; ``` backport は、一応同じ問題が起こるので required にしておきました。 (rescue や ensure での起動時、脱出時にイベントが欲しい、という話はあるかもしれないけど、別の話です) (あ、これで割り込み禁止にする、とかの処理を挟む...? うーん、筋が悪いかな) -- https://bugs.ruby-lang.org/