Actions
Bug #9957
closedTracePoint catch b_return at rescue/ensure
Bug #9957: TracePoint catch b_return at rescue/ensure
Description
TracePonit では b_return という、ブロックから出る時のイベントがあるのですが、rescue 節から大域脱出で抜けるとき、誤って b_return イベントを発生させていました。そのため、次のようなテストで失敗します。ブロックが無いのに b_return が発生してしまっています。
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 これは、フレームの構造をブロック呼び出しと同じようにしていたのが原因です。
次のパッチで修正できます。
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<<VM_FRAME_MAGIC_MASK_BITS)) #define VM_FRAME_TYPE(cfp) ((cfp)->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 での起動時、脱出時にイベントが欲しい、という話はあるかもしれないけど、別の話です)
(あ、これで割り込み禁止にする、とかの処理を挟む...? うーん、筋が悪いかな)
Updated by ko1 (Koichi Sasada) over 11 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
Applied in changeset r46463.
- vm_core.h: add VM_FRAME_MAGIC_RESCUE to recognize normal block or
rescue clause. - vm.c (vm_exec): use VM_FRAME_MAGIC_RESCUE on at rescue/ensure.
- test/ruby/test_settracefunc.rb: should not invoke b_return at rescue
clause.
[Bug #9957] - vm_dump.c (control_frame_dump): check VM_FRAME_MAGIC_RESCUE.
- vm_dump.c (vm_stack_dump_each): ditto.
Updated by nagachika (Tomoyuki Chikanaga) over 11 years ago
- Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED to 2.0.0: REQUIRED, 2.1: DONE
Backported into ruby_2_1 branch at r47012.
Updated by usa (Usaku NAKAMURA) about 11 years ago
- 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.
Actions