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