Next: Sending Patches, Previous: Understanding Bug Reporting, Up: Bugs [Contents][Index]
バグを報告する前に、まずその問題がすでに報告されていないか、確認を試みてください(Known Problemsを参照してください)。
もし可能なら、その問題がすでにfixされていないか、最新リリース版のEmacsも試してみてください。同様に、最新の開発版を試してみるのもよいでしょう。これがある人にとっては簡単でないことは認識しているので、バグを報告する前に、絶対にこれを行なわなければならないと思わないでください。
Emacsでバグレポートを書くベストな方法は、コマンドM-x report-emacs-bugを使用する方法です。これはメールバッファー(Sending Mailを参照してください)をセットアップして、自動的にいくつかの重要な情報を挿入します。しかし、すべての必要な情報は提供できません。だから以下のガイドラインを読んで、それに従うべきです。そうすればメッセージを送る前に、他の重大な情報を手で入力できます。M-x report-emacs-bugによって挿入されたいくつかの情報は、適切ではないと感じるかもしれませんが、完全に確信があるのでなければそれを残してください。そうすれば開発者たちがそれを判断できます。
レポートを記述し終えたら、C-c C-cとタイプすると、それはEmacsメンテナー bug-gnu-emacsに送られます (新しい機能や改善を提案したいときも、同じアドレスを使用します)。Emacsの中からメールを送れない場合、バグレポートのテキストを通常使用しているメールクライアントにコピーして(システムがサポートしている場合は、C-c M-iでEmacsにそれを行なわせることができます)、そのアドレスに送信できます。または、そのアドレスに問題を説明する簡単なメールを送ることもできます。
レポートは‘bug-gnu-emacs’メーリングリストに送られ、http://debbugs.gnu.orgのGNU Bug Trackerに保管されます。報告について、より詳細な情報を尋ねる必要がある場合のために、どうか有効な返信用アドレスを含めてください。提出されたレポートは調停されるので、レポートが見られるようになるまで遅れが生じることもあります。
バグを報告するためにGnu Bug Trackerがどのように機能するか知る必要はありませんが、もし望むなら、トラッカーのオンラインドキュメントで、使用できるさまざま機能を見ることができます。
‘bug-gnu-emacs’メーリングリストに送られたすべてのメールは、‘gnu.emacs.bug’ニュースグループにもゲートウェイされます。この逆も真ですが、バグレポート(または返信)をニュースグループにポストしないでください。これにより、さらに情報を尋ねるためにあなたに連絡するのが困難になるのと、それがバグトラッカーと充分に統合されていないからです。
データが500,000バイトを超える場合は、どうかそれを直接レポートに含めないでください。要求されたら送るという提案に留めるか、データをFTPで利用可能にしてその場所を知らせてください。
メンテナーがバグを詳細に調べられるように、レポートには以下の事項を含めるべきです:
この情報は、M-x report-emacs-bugにより自動的にレポートに含まれますが、レポートでこのコマンドを使用しない場合は、M-x emacs-version RETとタイプして、バージョン番号を取得できます。このコマンドが機能しない場合、たぶんあなたはGNU Emacsではない他の何かを使っているので、どこか他のところにそのバグを報告する必要があるでしょう。
configure
に与えたオプション(M-x
report-emacs-bugにより自動的にレポートに含まれます)。
これらの変更について正確に記述してください。英語による説明では充分ではありません。それらにたいするコンテキストdiffも送ってください。
独自のファイル追加や、他の機種へのポートも、ソースの変更です。
ファイルをvisitせずに問題を発生させる方法を説明できるなら、ぜひそうしてください。これによりデバッグがとても簡単になります。ファイルが必要な場合、わたしたちがファイルの正確な内容を見られるよう確実にしてください。たとえば、行末にスペースがあるか、バッファーの最終行の後に改行があるかが問題となる場合があります(最終行が終端されているかどうかを心配すべき理由はないかもしれませんが、それがバグだと報告することを試みてください)。
Emacsへの入力を正確に記録する方法の1つとして、それをdribbleファイルに書き込む方法があります。このファイルを開始するには、M-x open-dribble-file RETコマンドを使用します。このコマンドからそのEmacsプロセスがkillされるまで、Emacsはすべての入力を指定されたdribbleファイルにコピーします。機密情報(パスワードなど)は、dribbleファイルへの記録を終了させることに注意してください。
TERM
の値)、その端末にたいする/etc/termcapの完全なtermcapエントリー(このファイルはすべての機種で同じではありません)、Emacsが実際に端末に送った出力。
端末出力を収集する方法は、以下のLisp式
(open-termscript "~/termscript")
を、Emacs開始直後に、M-:を使用するか、*scratch*バッファーで実行します。その後Emacsプロセスがkillされるまで、Emacsはすべての端末出力を、指定されたtermscriptファイルにもコピーします。Emacs開始時にその問題が発生する場合は、この式をEmacs初期化ファイルに記述すれば、Emacsが最初にスクリーンを表示するときに、termscriptファイルもオープンされます。
警告: バグをシミュレートする端末タイプへのアクセスなしに、端末依存バグをfixするのは、しばしば困難で、不可能なときもあります。
echo LC_ALL=$LC_ALL LC_COLLATE=$LC_COLLATE LC_CTYPE=$LC_CTYPE \ LC_MESSAGES=$LC_MESSAGES LC_TIME=$LC_TIME LANG=$LANG
別の方法として、システムにそれがある場合は、GNU/LinuxおよびUnixコマンドを使用して、localeセッティングを表示できます。
M-!コマンドを使用してEmacsからこれらのコマンドを実行して、*Messages*バッファーからコマンドの出力をバグレポートにコピーできます。かわりにM-x
getenv RET LC_ALL
RETとタイプすると、LC_ALL
の値をエコーエリアに表示するので、*Messages*バッファーからこの出力をコピーすることもできます。
もちろん、Emacsが致命的なシグナルを受け取るというバグなら、見逃すことはないでしょう。しかし、そのバグが正しくないテキストの場合、メンテナーは何が間違っているか気づかないかもしれません。なぜそのような危険を放置するのですか?
あなたが遭遇した問題が致命的なシグナルの場合でも、明示的にそれを告げるべきです。何か奇妙なこと — たとえばあなたのソースコピーの同期がとれていない、またはあなたのシステムのCライブラリーにバグがある(これはあり得ます) — が起こっているとしましょう。あなたのコピーはクラッシュするかもしれませんが、私たちのコピーはクラッシュしないでしょう。あなたがクラッシュすることを告げていれば、わたしたちのEmacsはクラッシュしないので、バグはなかったとわたしたちは言うことができます。クラッシュすることを告げていない場合、わたしたちはバグがあるかどうか知ることができません — わたしたちの観察から、なんらかの結論を描くことも不可能です。
エラーメッセージを正確に取得するには、それを*Messages*バッファーからバグレポートにコピーします。一部だけではなく、すべてをコピーしてください。
エラーにたいするbacktraceを作成するには、エラーが発生する前にM-x toggle-debug-on-errorを使用します(つまり、このコマンドを与えた後で、バグを発生させなければなりません)。これはエラーによりbacktraceを表示するLispデバッガーを開始します。デバッガーのbacktraceをバグレポートにコピーしてください。EdebugパッケージでEmacs Lispプログラムをデバッグする情報については、Edebug in the Emacs Lisp Reference Manualを参照してください。
このデバッガーの使用は、バグを再現する方法を知っているときだけ利用可能です。バグを再現できなければ、最低でもエラーメッセージ全体をコピーしてください。
Emacsが無限ループや、とても長い処理にハマっているように見えるとき、(変数debug-on-quit
が非nil
の場合は)C-gとタイプするとLispデバッガーを開始して、backtraceを表示します。このbacktraceは、そのような長いloopのデバッグにたいして有用なので、backtraceを生成できたら、バグレポートにコピーしてください。
(inhibit-quit
がセットされている等で)、C-gにEmacsが応答しない場合、Emacsの外からdebug-on-event
で指定されたシグナル(デフォルトはSIGUSR2)を送ることにより、デバッガーに入ることができます。
-Q
スイッチでEmacsを開始することによりinitファイルのロードを抑止できます)。それで問題が発生しなかったら、問題を発生させるためにLispの世界にロードしなければならないプログラムの、正確な内容を報告しなければなりません。
開発ソースの行番号と、あなたのソースの行番号は一致しません。行番号だけでは、あなたのバージョンでその行番号がどのコードをさすのか、メンテナーが判断するのに余分な作業を要しますし、それに確信をもつこともできません。
しかし、何がバグを引き起こしたかを示すような追加の情報を収集するときは、考える必要があります。
たとえば、多くの人はbacktraceだけを送って着ますが、これだけではとても有用とは言えません。引数つきのシンプルなbacktraceは、GNU Emacsの中で何が起こっているかを少ししか伝えないことがしばしばです。なぜならbacktraceにリストされたほとんどの引数は、Lispオブジェクトへのポインターだからです。これらのポインターの数値は、何であれ意味をもちません。問題となるのはポインターが指すオブジェクトの内容(そして、その内容自身もポインターの場合がほとんどです)なのです。
有用な情報を提供するためには、Lispオブジェクトの値をLisp表記で示す必要があります。基底スタックの近傍のスタックフレームのいくつかで、Lispオブジェクト変数それぞれにたいしてこれを行ないます。どの変数がLispオブジェクトであるかはソースを調べます。なぜならデバッガーはそれらを整数と判断するからです。
Lisp構文で変数の値を表示するには、最初にその値をプリントして、それからLispオブジェクトをLisp構文でプリントするために、ユーザー定義のGDBコマンドpr
を使用します(他のデバッガーを使用しなければならない場合、そのオブジェクトを引数として、関数debug_print
を呼び出します)。pr
コマンドはファイル.gdbinitで定義されていて、(コアダンプではなく)実行中のプロセスにたいしてデバッグするときだけ機能します。
LispエラーでEmacsを停止させてGDBに戻るには、Fsignal
にブレークポイントを置きます。
実行中のLisp関数の短いリストのためには、GDBコマンドxbacktrace
をタイプします。
ファイル.gdbinitでは、データ型やLispオブジェクトの内容を調べるための、他のコマンドも定義されています。これらのコマンドの名前は‘x’で始まります。これらのコマンドはpr
より低いレベルで動作するので、少し不便になりますが、コアダンプをデバッグしていたり、Emacsが致命的なシグナルを受け取ったときなど、pr
が機能しないようなときでも、機能するでしょう。
Emacsのデバッグにたいする、より詳細なアドバイスと、他の有用なテクニックは、Emacsディストリビューションの、ファイルetc/DEBUGで利用可能です。そのファイルには、Emacsが応答しない問題を詳しく調べる手順も含まれています(多くの人はこれをEmacsが“ハング”したとみなしますが、実際はおそらく無限ループにハマっているのでしょう)。
インストールしたEmacsのファイルetc/DEBUGを探すには、変数data-directory
に保管されたディレクトリー名を使用します。
以下はバグレポートには不要な事柄です:
バグに遭遇したとき人は、入力ファイルを変えてバグが発生しなくなるか、影響がないかなどを詳しく調べるのに、多くの時間を費やすことがしばしばです。
これは大抵多くの時間がかかる割に、とても有用とは言えません。なぜならわたしたちがバグを探す方法は、ブレークポイントを設定したデバッガーの元で1つの例を実行することであり、一連の例から得られる推論ではないからです。追加の例を探すのを止めることにより、あなたも時間を節約できるでしょう。すぐにバグレポートを送って、編集作業に戻り、報告すべき他のバグを探す法がよいでしょう。
もちろんオリジナルのかわりに、簡単な例を見つけることができたら、そちらのほうが便利です。出力中のエラーは簡単に見分けられますし、デバッガーでの実行も時間が短くなります
しかし単純化は必須ではありません、これを行なうことができなかったり、試す時間がない場合は、どうかオリジナルのテストケースでバグを報告してください。
コアダンプによるデバッグは有用ですが、それはあなたのEmacs実行ファイルと、あなたのマシンだけで行なうことができます。したがってEmacsメンテナーにコアダンプを送るのは、有益ではないでしょう。何よりも、コアダンプをメールのバグレポートに含めないでください! そのような巨大なメッセージは、すこぶる迷惑です。
システムコールトレースは、ある特別な種類のデバッグにはとても有用ですが、有用な情報が少ない場合がほとんどです。したがって、クラッシュに関する情報を報告する一番の方法は、システムコールトレースを送ることだと考えているように思える人が多いのは奇妙です。おそらくソースコードやデバッグシンボルがないプログラムをデバッグする経験がもたらす、習慣的なやり方なのでしょう。
ほとんどのプログラムでは、システムコールトレースより、backtraceのほうが、通常はずっとずっと参考になります。完全な情報を得るには、変数の値を表示して、それらをpr
でLispオブジェクトとしてプリントすることによりbacktraceを補完すべきであるとはいえ、シンプルなbacktraceのほうが一般的により参考になります(上記参照)。
バグにたいするパッチは、それが良いものなら有用です。しかし、そのパッチで充分だと思い込んで、テストケースのような、バグレポートに必要な他の情報を省略しないでください。わたしたちはそのパッチに問題を見つけて別の方法でfixすると判断するかもしれないし、結局はそれを理解できないかもしれません。わたしたちが、あなたがfixしようと試みているバグを理解できなければ、そしてなぜそのパッチが改善なのかを理解できなければ、私たちはそれを採用できません。
わたしたちにパッチを理解させて、採用を簡単にするためのガイドラインについては、Sending Patchesを参照してください。
そのような推測は通常間違っています。エキスパートでさえ、事実を見つけるために最初にデバッガーを使用しなければ、そのような事柄を正しく推測できないのです。