Issue #10689 has been updated by Kazuki Tsujimoto. vm_throw_start内にあるflagが立っている場合の処理は 以下のように整理できるんじゃないかと思うのですがどうでしょう。 ~~~diff diff --git a/vm.c b/vm.c index 45734e1..80b3bbe 100644 --- a/vm.c +++ b/vm.c @@ -1523,7 +1523,7 @@ vm_exec(rb_thread_t *th) } } } - else if (state == TAG_BREAK && ((VALUE)escape_cfp & ~0x01) == 0) { + else if (state == TAG_BREAK && !escape_cfp) { type = CATCH_TYPE_BREAK; search_restart_point: diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 05b8d15..744bbfd 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -600,8 +600,8 @@ vm_throw_start(rb_thread_t * const th, rb_control_frame_t * const reg_cfp, int s rb_control_frame_t *escape_cfp = NULL; const rb_control_frame_t * const eocfp = RUBY_VM_END_CONTROL_FRAME(th); /* end of control frame pointer */ - if (flag != 0) { /* TODO: memo */ - escape_cfp = (void *) 0x01; + if (flag != 0) { + /* do nothing */ } else if (state == TAG_BREAK) { int is_orphan = 1; ~~~ ---------------------------------------- Bug #10689: `unexpected break' occurs when TracePoint#binding is called https://bugs.ruby-lang.org/issues/10689#change-50927 * Author: Kazuki Tsujimoto * Status: Open * Priority: Normal * Assignee: * Category: core * Target version: * ruby -v: ruby 2.3.0dev (2015-01-02 trunk 49102) [x86_64-linux] * Backport: 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: REQUIRED ---------------------------------------- 以下のコードでunexpected breakになります。 ~~~ruby class Bug include Enumerable def each [0].each do yield end end end TracePoint.trace(:c_return) do |tp| tp.binding end Bug.new.all? { false } ~~~ all?中のrb_iter_breakによってth->errinfoがセットされた後に、 TracePoint#binding呼び出しによってcfpのepがヒープを指すようになってしまうのが原因です。 とりあえずTracePoint呼び出し後にth->errinfoのepを書き換えるようにしてみたパッチを添付します。 ---Files-------------------------------- fix-unexpected-break.patch (3.32 KB) save-target-cfp-in-errinfo.patch (6.26 KB) -- https://bugs.ruby-lang.org/