[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 以降で挙動が違います。

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 ではおきない)

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs