言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

デバッガ起動の仕組み

例えば、1をゼロで割るとどうなるだろうか? ご存知の通り、これは典型的なエラーだ。例外を発生し、誰もトラップしていなかったらシステム終了。だけど Smalltalk はこのくらいの事で落ちる訳にもいかない。すぐさまデバッガが起動して、一体何が悪かったのかを教えてくれる。私たちは日常的にこういう作業を繰り返す。あれ? でも何かがおかしい。

1/0 を VisualWorksワークスペースで実行してみよう。実行するのは、いまここにいる私と、それに付き合うワークスペースのプロセス。よくオブジェクト指向はメッセージを交換しあうなんて言うけど、本当は一つのプロセスがオブジェクトを一つ一つ渡り歩くイメージの方が現実に近い。すると、プロセスがまるで自我のように思えてくる。おもむろに Do it を実行すると、例外の通知が表示されるので、デバッグ画面を出す。すると先程の 1/0 が、いかに失敗したかを事細かに教えてくれ、望むなら時間を巻き戻したり続きをステップ実行出来る。

問題はここだ。Do it した瞬間のプロセスは我々と共にあった。しかし今ではそのプロセスはデバッガの管理下にあって、外から操作出来る。いわば、今まで自分だと思っていた物体を幽体離脱して外から眺めている状態になってしまっている。この切り替えは何処で行われたのか? 私は何処へ行ったのか? 機械だから簡単でしょとは言わないで、実は自分でやってみようとすると難しいのだ。

  • デバッグの為に、新しくプロセスを作る必要がある。私たちは古いプロセスを捨て、新しいプロセスからデバッグを行う必要がある。
  • デバッグの為に、古いプロセスは履歴(スタック)を保ったまま新鮮な状態でなくてはいけない。古いプロセスは新しいプロセスを作った後で自分自身を瞬間冷凍させる必要がある。

では、具体的にどうやってるか。

  • DebuggerService class>>openException: に例外が渡される
  • DebuggerService class>>openContext:label:proceedable:interrupted: にて、新しいプロセスが作られる訳だが、その中で、
    • ProcessHandle>>prepareForErrorCondition で古いプロセスがもはやユーザの主役では無いことを設定した後、
    • 古いプロセスを proc に入れて一時停止。
    • DebuggerService class>>openDebugger:contents:label:proceed:displayAt: でデバッガ画面を出力した後、
    • WindowManager>>launchBaseProcess で古いプロセスを乗っ取る。

で、合ってるかな。
なんでこんなことしてるかというと、Croquet ではこういう仕組みが全然働かなくて困っているのだ。