debugger

Profiles

Introduction

Yet another debugger using dRuby. You can attach a debuggee and debug it from foreign host. Even if the application which eats STDIN and dumps to STDOUT, it can be debugged.

Requirement

Yet Another Ruby Debugger works under ruby 1.6.2. And dRuby 1.3.x must be installed.

Install

  1. Get the package and extract it.
  2. Copy debuggee.rb to appropriate directory in your $LOAD_PATH.

Usage

To debug sample/target.rb, type like this to run the application.

$ ruby -rdebuggee sample/target.rb

This kind of message are dumped

Debug dRuby-URI: druby://foo:46166

sample/target.rb which is a debuggee, is at a stop now. Then, at another window (or the like), type like this to attach the application. (Of course you must 'cd' to the directory where debugger.rb locates.)

$ ./debugger.rb druby://foo:46166

Your application (debuggee) and debugger.rb can be run at separate hosts. (This is the existence of this debugger :D )

How it works.

In YARD, there are 2 programs;

  1. debuggee.rb which must be loaded to a debuggee program like 'ruby -rdebuggee targetProgramToBeAttached.rb'. When debuggee.rb is loaded to a program, debuggee.rb set up dRuby interface, stops execution of the target program and waits to be attached from a debug client.
  2. debugger.rb which is a CUI front-end and tries to attach debuggee.rb via dRuby. It accepts inputs from STDIN then send it to debuggee.rb as a dRuby request, and receives outputs from debuggee.rb via dRuby then dumps it to STDOUT.

If you don't want to use dRuby, you have to look for alternatives to connect to debuggee. Native TCP socket, PIPE, SOAP :-), etc. Though I don't know [RAA:RDE(Ruby Development Environment)] well, RDE seems to use PIPEs for sending request and receiving output.

Link

Comments

(Your comment makes me happy.)

for Japanese/日本語

デバッガを使わないアプリ開発

NaHiには想像できません.

Linusくんがkernel mode側にはデバッガは要らない,と言うのはわからないでもありません. 全部把握できるやつじゃなきゃお呼びじゃない,ってことでしょう. お呼びじゃないNaHiは使うけどね.

それとは別に,user mode側で,各種ライブラリ組み合わせてアプリ作る以上, デバッガを使わない開発なんて, 聴診器使わずにいきなりメス入れる医者みたいなもんです(暴言

IntrospactionとDebuggerって似てるかも。 生きてるブツのハラワタ覗けるっていう意味で。 そいやDelphi5のブレークポイントは、 それ自体がオブジェクトであるような気がする。 つまり覗かれる側も覗く側もオブジェクト。

Rubyであればこそ

デバッガを活用して欲しいとも思う.しかも上記「Ruby本体にdebug APIを入れる方式」でなく, 現在の「デバッガもRuby script方式」であれば,Rubyのdynamismを思う存分に活用できる.

C++のデバッガにおいて,とあるscopeでbreakして, そのスコープ中のインスタンスのメンバ関数を起動するなんて,なかなかできないわけですよ. でもRubyなら平気.evalしちゃえばいい(debug.rbがしてくれる). そこでインスタンスの中身を書き換えて続行しても全く問題なし. ああ素晴らしきdynamism. -NaHi

誰も使わなくたって

NaHiが使うんだからよいのだ(自己の正当化). というわけで.

はじまり

そのうちdebug.rbをdRuby対応しようと思う.

require 'debuggee' if $DEBUG

とかいうコードを埋め込んでおいて-d付きで起動した場合(デバッグコンパイルに相当), dRubyクライアントからattachできるようなやつ.

第一世代は現状のdebug.rbを流用して作る. 第二世代ではdebuggeeにdebug用threadを打ち込む形にしたい. これならRuby本体にdebug APIを入れなくても,かなり高速化できる.

第一世代始動

とりあえず第一世代の最初のバージョンが動いた.dRuby万歳. 作り始めてすぐ動くんだから,dRubyの生産性ときたら素晴らしい.

速度

残念ながら今までのdebug.rbに比べてさらに遅いけど, 少しずつチューニングしていこう.

シグナルをどうしよう

debuggerから,attachしたdebuggeeに対してSIGINTを送りたいのだ. 以前に作ったrdebugは,process IDを送ってもらってProcess.killしていた. しかし今回はdRubyを使う以上, debuggerとdebuggeeが同一マシンであることを期待すべきではない.

メソッド叩いて,signalをエミュレートするのが正統派かな. でもrdebugの時に何故かうまくいかなかったんだよね...

tracer

tracer.rbは組み込みのprintやprintfを呼んでいるので, trace onするとdebuggee側のSTDOUTが汚れてしまう. dRuby経由でdebugger側に送らないといけない. tracer.rbに手を入れずになんとかする方法はないかな...

ハイゼンベルグ効果

debuggee.rbがDRb.start_serviceしたら,デバッギがDRb.start_serviceしてる時に 混乱しちゃうじゃんねぇ.なにが「なんとなくrwiki.rbも追えてたりする」なんだか.

いろいろあって,さんがdRuby開発版で,1プロセスが複数サーバを 持てるようにしてくださったのだった.これで一歩前進.感謝.(^-^

DEBUGGER__.interrupt

現在のdebug.rbは,SIGINTをtrapしてDEBUGGER__.interruptを呼び出す. DEBUGGER__.interruptは@last_threadに対してstop_nextを呼び出す. 最後にデバッグしていたthreadが次に何かを実行しようとしたら止まるわけ. つまりrwiki.rbみたいに,全threadがsleepしていたりすると,即座には止まらない.

まぁこれは現在のdebug APIでは仕方ない(避けようがない).

さて問題はDEBUGGER__.interruptなんだけど,本当に@last_threadにstop_nextで いいんだろうか.たまたま@last_threadがsleepしてたりすると,他にrunのthreadが あるのに止まらないことになる.

どのthreadでもどのファイルでもいいから,次になにか実行しようとしたら止まる, という機能を追加するかな.

スレッドのデバッグ

[ruby-dev:11732]からの続き。いろいろ考えてみよう。

こんなところかなぁ。

86系の石だとタスクごとにデバッグレジスタを持っているので、 それぞれ別々にbpを設定できる。が、NaHiは C/C++レベルでその機能を活用してるデバッガを見たことがない。あるのかなぁ。 関係ないthreadは裏で走りつづけると言うのは、Rubyらしくて面白い。

ちなみにYA debuggerも、dRuby threadだけ走らせ続けてるから、 リモートマシンからdebugできるんだよ。誰も聞いてないねそんなことは。

結局以下のようにした。

「した」はいいんだけど、なかなかうまく実装できない。最後のヤツが問題なのだ。。。

セキュリティとか

debuggee付きで起動したら誰でもプロセスがいじれてしまう?-ZnZ

そうです。気をつけてください。念のため、なひはデバッグとは そういうもんだと理解してます。NTをdebugger enabled状態で起動してほっといたら、 ケーブルつながれてWinDbgで捕まえられちゃいますよ、並にどうしようもない。^^; --NaHi

debugger はサーバになれるか?

debuggee が debugger に接続して…という形態は可能でしょうか? debugger が特定のURIで常に起動していて、なおかつデバッギを そのURIを環境変数とかで指定して起動させるなんてことができれば、 頻繁にデバッギ側を書き直して立ち上げ直してというのが楽になるのですが。



The RWiki