トップ «前の日記(2011-01-07 (Fri)) 最新 次の日記(2011-12-12 (Mon))» 編集 RSS feed

継続にっき

2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
2009|01|05|12|
2010|04|05|11|
2011|01|09|12|
2012|02|03|05|09|12|
2013|02|03|
2014|05|09|
2015|12|
2017|09|

2011-09-18 (Sun)

))) Rubyの例外終了時に自動でREPLを起動する

Rubyが例外を吐いて終了する際に、例外発生時点の環境で自動でREPLが起動するようになっていればデバッグ楽だよなぁと思っていたのだけど、 1つ実装方法をひらめいたのでライブラリを作ってみた。

これを使うと以下のようなことが出来るようになる。

$ ruby -rdebug-exception -e '
  def f(i)
     raise "test"
  end

  f(0)
'
RuntimeError: test
        from -e:3:in `f'
        from -e:6:in `<main>'
irb#1(main):001:0> i
=> 0

debug.rbやruby-debugと比較したときのこのライブラリのメリットは以下の2点*1

  • キャッチする例外をあらかじめ指定したり、ソースコードを変更しておいたりする必要がなく、ライブラリをロードしておくだけで使えるので楽。
  • 例外オブジェクトが生成されない限りオーバーヘッドはないので高速*2。開発時は常時requireしておいても問題ないぐらいのパフォーマンスは出るはず。

ただ、今のRubyはデバッグ用に使えるAPIがあまり整備されていないのでこの実装も機能制限付きな部分がある。 (例えばinitializeを再定義しているようなユーザ定義例外クラスを使うとうまく動かない)

2012/04までにこのあたりを何とかするという話も出ているので、 それにあわせてもう少しまともに作っておくと便利かな。

*1 ruby-debugはしっかり使ったことないので外しているかも。

*2 StandardErrorのinitializeの中で直近のbindingを保存させるようにするというのが基本的な考え方。

本日のツッコミ(全3件) [ツッコミを入れる]
_ なかだ (2011-09-18 (Sun) 16:38)

どういう機能がほしいかあげてもらえると助かります。

_ k_tsj (2011-09-18 (Sun) 20:33)

この機能に必要なものに絞って話をすると、[ruby-dev:44024]他で議論されているAPIがあればよさそうです。 <br>ある程度汎用的にするにはcfpを返すAPIとcfpからbindingを生成するAPIに分けた方が良いかもしれません。(ruby-debugの実装を見ていないので適当なことを言っているかも) <br> <br>また、今の実装で気になっている点として「StandardError#initialize中のrb_binding_new呼び出しで例外が起きるとスタックを食いつぶしてしまう可能性がある」「トップレベルまで伝播した例外をat_exitで扱うことの是非」があるのですが、Rubyのコア機能としてこれらのケアが必要かどうかはまだ判断できていません。 <br>単に実装がまずいだけのような気もします。 <br>

_ k_tsj (2011-09-18 (Sun) 21:11)

む、今更気づいたけどこのアプローチだと例外の生成とraiseを全く無関係の場所で行ってしまうと対応できないな。


2004|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|12|
2006|01|03|05|06|08|09|10|12|
2007|01|02|03|05|07|12|
2008|10|
2009|01|05|12|
2010|04|05|11|
2011|01|09|12|
2012|02|03|05|09|12|
2013|02|03|
2014|05|09|
2015|12|
2017|09|
トップ «前の日記(2011-01-07 (Fri)) 最新 次の日記(2011-12-12 (Mon))» 編集 RSS feed