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/