From: ko1@... Date: 2014-06-13T08:50:19+00:00 Subject: [ruby-dev:48291] [ruby-trunk - Bug #9940] [Closed] Unexpected throw from TracePoint hooks with recursive checking Issue #9940 has been updated by Koichi Sasada. Status changed from Open to Closed % Done changed from 0 to 100 Applied in changeset r46419. ---------- * vm_trace.c: clear and restore recursive checking thread local data to avoid unexpected throw from TracePoint. [Bug #9940] * test/ruby/test_settracefunc.rb: add a test. * thread.c: adde * rb_threadptr_reset_recursive_data(rb_thread_t *th); * rb_threadptr_restore_recursive_data(rb_thread_t *th, VALUE old); * vm_core.h: ditto. ---------------------------------------- Bug #9940: Unexpected throw from TracePoint hooks with recursive checking https://bugs.ruby-lang.org/issues/9940#change-47208 * Author: Koichi Sasada * Status: Closed * Priority: Normal * Assignee: Koichi Sasada * Category: core * Target version: current: 2.2.0 * ruby -v: ruby 2.2.0dev (2014-06-13 trunk 46416) [i386-mswin32_110] * Backport: 2.0.0: UNKNOWN, 2.1: REQUIRED ---------------------------------------- 下記のようなプログラムで、2.0 と 2.1 以降で挙動が違います。 ```ruby stack = [] TracePoint.new(:c_call){|tp| mid = tp.method_id begin p mid stack << mid # (*) ensure stack << mid end }.enable{ p 1 } p stack # Ruby 2.0 => [:p, :p, :hash, :hash, :inspect, :inspect] # Ruby 2.1, 2.2 => [:p, :p, :hash, :inspect, :inspect] ``` 具体的には、c-call -> :hash を実行中に、意図しない大域脱出が発生しているためです。 理由を下記に述べます。 (1) `p 1` を実行するとき、rb_uninterruptible() が呼ばれます (2) rb_uninterruptible() は、rb_hash_aset() を呼び出します (3) rb_hash() を実行するときに、recursive check を走らせます (4) recursive check 実行中に、rb_hash() -> #hash メソッドを呼び出します (5) #hash メソッドが TracePoint (c_call) を呼び出します (6) TracePoint 中で `p 2` を走らせようとします (7) (1)~(4) と同様の処理を走らせようとして、同じ key を見つけてしまい、throw して、(4) へ戻ります (8) throw するとき、TracePoint 中の ensure 節はちゃんと実行するので、1 つだけ :hash が残ります というわけで、TracePoint 実行するタイミングで中途半端に recursive check 用のデータが残っているのが問題です。 これを解決するために、TracePoint 実行会s時に recursive check 用のデータをクリアし、戻るときに復帰するようにしようと思います。 2.1 でもおきますが、直すにはちょっとニッチだったりしますかねぇ。 (なぜか 2.0 ではおきない) -- https://bugs.ruby-lang.org/