Bug #10689
closed`unexpected break' occurs when TracePoint#binding is called
Description
以下のコードでunexpected breakになります。
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
Updated by ktsj (Kazuki Tsujimoto) over 10 years ago
I'll try to change throw mechanism (not save target dfp, but save target cfp).
この方針でパッチを書き直しました。
Updated by ko1 (Koichi Sasada) over 10 years ago
ありがとうございます!
頂いたパッチを元に、cfp を使うように整理してみました。
http://www.atdot.net/sp/view/e5ivhn
- vm_throw() を簡素化
- マクロっぽい名前を関数っぽく
一応、test-all/test-rubyspec は通っていますが、良さそうでしたらコミットしてもらえないでしょうか。
Updated by ktsj (Kazuki Tsujimoto) over 10 years ago
vm_throw_start内にあるflagが立っている場合の処理は
以下のように整理できるんじゃないかと思うのですがどうでしょう。
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;
Updated by ko1 (Koichi Sasada) over 10 years ago
なんのために 0x02 の bit について気にしていたか覚えていないのですが(クラスとか、その辺でしたっけ)、
よろしいと思います! よろしくお願いします。
Updated by ktsj (Kazuki Tsujimoto) over 10 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
Applied in changeset r49266.
-
eval_intern.h, vm.c, vm_eval.c, vm_insnhelper.c:
change throw mechanism (not save target ep, but save target cfp).
It fixes `unexpected break' bug that occurs when
TracePoint#binding is called.
[ruby-dev:48797] [Bug #10689] -
test/ruby/test_settracefunc.rb: add a test.
Updated by ktsj (Kazuki Tsujimoto) over 10 years ago
レビューありがとうございます。
なんのために 0x02 の bit について気にしていたか覚えていないのですが(クラスとか、その辺でしたっけ)、
VM_ENVVAL_BLOCK_PTR_FLAGのことかなぁと思っていました。
Updated by naruse (Yui NARUSE) over 10 years ago
- Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: REQUIRED to 2.0.0: REQUIRED, 2.1: REQUIRED, 2.2: DONE
ruby_2_2 r49374 merged revision(s) 49266.