バグを報告する前に、まずはその問題がすでに報告されていないか確認してください(既存のバグレポートと既知の問題の読み方を参照してください)。
可能であれば、Emacsの最新リリースを試して、問題がすでに修正されているか確認してみてください。さらに良いのは、最新の開発版を試すことです。これが一部の方にとって容易ではないことは承知しておりますので、報告を行う前に必ずそうしなければならないとは思わないでください。
Emacsのバグレポートを作成する最善の方法は、M-x report-emacs-bugコマンドを使用することです。これによりメールバッファが作成され(メールの送信を参照)、不可欠な情報の一部が自動的に挿入されます。ただし、これだけでは必要な情報をすべて提供できるわけではありません。メッセージを送信する前に、その他の重要な情報を手動で入力できるよう、引き続き以下のガイドラインを読み、それに従ってください。M-x report-emacs-bugによって挿入される情報の中には、関連性がないと感じるものもあるかもしれませんが、完全に確信が持てない限りは、開発者が自ら判断できるよう、そのままにしておくのが最善です。
レポートの作成が完了したら、C-c C-c と入力してください。すると、bug-gnu-emacs の Emacs メンテナーに送信されます。Emacs 内からメールを送信できない場合は、レポートの本文を普段お使いのメールクライアントにコピーし(システムが対応していれば、C-c M-i と入力して Emacs に代行させることも可能です)、そのアドレスに送信してください。あるいは、以下に記載する必要な情報を添えて、問題の内容を説明したメールをそのアドレスに直接送信することもできます。
Emacsにコードを提出したい場合(問題の修正や新機能の実装など)、最も簡単な方法はEmacsのイシュートラッカーにパッチを送ることです。その際はM-x submit-emacs-patchコマンドを使用してください。これはバグ報告時とほぼ同様に動作します。詳細はGNU Emacsへのパッチ送信を参照してください。
いずれにせよ、ご報告内容は‘bug-gnu-emacs’メーリングリストに送信され、https://debbugs.gnu.orgのGNU Bug Trackerに保存されます。ご報告内容についてさらに情報をいただく必要がある場合に備え、有効な返信先メールアドレスを記載してください。投稿内容はモデレーションの対象となるため、実際にトラッカーに反映されるまで時間がかかる場合があります。
バグを報告するのに、GNU Bug Trackerの仕組みを理解している必要はありませんが、もし知りたい場合は、トラッカーのオンラインドキュメントを参照して、利用可能な各種機能を確認できます。
‘bug-gnu-emacs’ メーリングリストに送信されるすべてのメールは、‘gnu.emacs.bug’ ニュースグループにも転送されます。その逆も同様ですが、ニュースグループ経由でバグレポート(または返信)を投稿することはご遠慮ください。追加情報を求める際に連絡が非常に困難になるほか、バグトラッカーとの連携も十分に行えません。
データが500,000バイトを超える場合は、バグレポートに直接含めず、代わりにリクエストに応じて送付することを申し出るか、オンラインで公開してその場所を明記してください。大容量の添付ファイルは、圧縮して送付するのが最適です。
GNU Bug Trackerはレポートにバグ番号を割り当てます。バグに関する議論がトラッカーに記録されるよう、受信者リストにバグアドレスを記載した上で、以降の議論ではその番号をご使用ください。バグアドレスは ‘nnnnn@debbugs.gnu.org’ という形式になり、nnnnn の部分がバグ番号となります。
メンテナーがバグを調査できるよう、レポートには以下の項目をすべて含めてください:
もちろん、バグがEmacsの致命的なシグナル発生であるなら、見逃すことはない。しかし、バグがテキストの誤りである場合、メンテナーは何が問題なのかに気づかないかもしれない。あえて運任せにする理由があるだろうか。
たとえ直面している問題が致命的なシグナルであったとしても、そのことを明示的に伝えるべきです。例えば、ソースのコピーが同期していない、あるいはシステム上のCライブラリにバグがあるといった、何か奇妙なことが起きているとしましょう。(実際にこのようなことが起こりました!)あなたのコピーではクラッシュし、こちらのコピーではクラッシュしないかもしれません。もしクラッシュすることを伝えていれば、こちらのEmacsがクラッシュしなかったとき、そのバグは発生していなかったことが分かります。クラッシュすることを伝えなければ、バグが発生していたのかどうか分からず――観測結果からいかなる結論も導き出すことはできないでしょう。
通常、動作の説明や問題の再現方法については、以下の項目のうち1つ以上を明記する必要があります。
ファイルを参照せずに問題を再現する方法を教えていただける場合は、ぜひそうしてください。そうすることでデバッグが格段に容易になります。もしファイルが必要な場合は、正確な内容が確認できるよう手配してください。例えば、行末にスペースがあるか、あるいはバッファの最終行の後に改行があるかといった点が重要になる場合があります(最終行が終端されているかどうかは本来問題にならないはずですが、バグ報告の際にはその点も伝えてみてください)。
Emacsへの入力を正確に記録する方法の一つに、ドリブファイルを作成する方法があります。ファイルを作成するには、M-x open-dribble-fileコマンドを使用してください。以降、Emacsプロセスが終了するまで、Emacsはすべての入力を指定したドリブファイルにコピーします。機密情報(パスワードなど)がドリブファイルに記録される可能性がある点にご注意ください。
エラーメッセージのテキストを正確に取得するには、*Messages*バッファからバグレポートにコピーしてください。一部ではなく、すべてをコピーしてください。
-Q スイッチを指定してEmacsを起動し、初期化ファイルのロードを防いでください)。もし問題が発生しない場合は、問題を発生させるためにLispワールドにロードする必要があるプログラムの正確な内容を報告してください。
開発元のソースの行番号が、そちらのソースのものと一致していません。特定の行番号においてどのコードがそちらのバージョンに含まれているかをメンテナーが判断するには追加の手間がかかりますし、確実性も担保できません。
TERM
の値)、/etc/termcap にある当該端末の完全な termcap
エントリ(このファイルはすべてのマシンで同一ではないため)、および Emacs が実際に端末に送信した出力。
ターミナル出力を収集するには、Emacsの起動直後にコマンド M-x open-termscript を実行してください。すると、Emacsプロセスが終了するまでのすべてのターミナル出力を記録するファイル名の入力が求められます。もし問題がEmacsの起動時に発生する場合は、以下のLisp式を記述してください。
(open-termscript "~/termscript")
Emacsの初期化ファイルに記述することで、Emacsが最初に画面を表示した際にtermscriptファイルが開くようになります。
ご注意ください。バグを誘発する種類の端末を利用できなければ、端末依存のバグを修正するのは困難なことが多く、時には不可能な場合もあります。
M-x report-emacs-bug はこの情報を自動的に含めますが、レポートでそのコマンドを使用していない場合は、M-x emacs-version RET と入力することでバージョン番号を取得できます。もしそのコマンドが動作しない場合は、おそらく GNU Emacs 以外のものを使用しているため、別の場所でバグを報告する必要があります。
configureコマンドに渡されたコマンドライン引数(M-x report-emacs-bugによって自動的に含まれる)。
これらの変更については具体的に記述してください。英語での説明だけでは不十分です—統一されたコンテキスト差分を送ってください。
自前のファイルを追加したり、別のマシンに移植したりすることは、ソースコードの改変にあたります。
echo LC_ALL=$LC_ALL LC_COLLATE=$LC_COLLATE LC_CTYPE=$LC_CTYPE \ LC_MESSAGES=$LC_MESSAGES LC_TIME=$LC_TIME LANG=$LANG
また、システムに搭載されていれば、localeコマンドを使用してロケール設定を表示することもできます。
バグレポートに記載する必要のない事項をいくつか挙げます。
バグに遭遇した人は、入力ファイルのどの変更でバグが解消され、どの変更では影響が出ないのかを調べるのに多くの時間を費やすことがよくあります。
この方法は、一連の例から純粋に推論するのではなく、ブレークポイントを設定したデバッガで単一の例を実行することでバグを探すため、手間がかかることが多く、あまり有用ではありません。追加の例を探さない方が、時間の節約になるでしょう。すぐにバグレポートを送信し、編集作業に戻って、報告すべき別のバグを探す方が得策です。
もちろん、元の例の代わりに報告できるよりシンプルな例が見つかれば、それは好都合です。出力のエラーも見つけやすくなりますし、デバッガでの実行時間も短縮されるでしょう。
ただし、簡略化は必須ではありません。それができない場合や、試す時間がない場合は、元のテストケースを添えてバグを報告してください。
コアダンプのデバッグは有用かもしれませんが、それはご自身のマシンで、ご自身のEmacs実行ファイルを用いてのみ可能です。したがって、コアダンプファイルをEmacsのメンテナーに送っても役に立ちません。何より、メールによるバグ報告にコアファイルを添付しないでください!これほど大容量のメッセージは、非常に不便な場合があります。
System-call traces are very useful for certain special kinds of debugging, but in most cases they give little useful information. It is therefore strange that many people seem to think that the way to report information about a crash is to send a system-call trace. Perhaps this is a habit formed from experience debugging programs that don’t have source code or debugging symbols.
ほとんどのプログラムにおいて、バックトレースは通常、システムコールトレースよりもはるかに、はるかに情報量が多くなります。Emacsでさえ、単純なバックトレースの方が一般的に情報量が多くなりますが、完全な情報を得るには、変数の値を表示し、それらをprでLispオブジェクトとして出力することで、バックトレースを補完する必要があります(上記参照)。
バグ修正パッチは、内容が適切であれば有用です。しかし、パッチさえあれば十分だという思い込みから、テストケースなど、バグレポートに必要なその他の情報を省略しないでください。パッチに問題が見つかり、別の方法で修正することにしたり、あるいは内容を全く理解できなかったりする可能性があります。また、どのようなバグを修正しようとしているのか、あるいはなぜそのパッチが改善になるのかが理解できない場合、インストールしてはいけません。パッチを分かりやすくし、インストールしやすくするためのガイドラインについては、GNU Emacsへのパッチ送信を参照してください。
こうした推測はたいてい外れる。専門家であっても、まずはデバッガを使って事実を確認しなければ、こうした事柄について正しく推測することはできない。
Emacsのデバッグを行い、バグに関する追加情報を提供していただける場合は、以下のアドバイスが役立つかと思います。
エラーをデバッグするには、Edebugの使用をお勧めします。Edebugパッケージを用いたEmacs Lispプログラムのデバッグに関する情報については、『Emacs Lispリファレンスマニュアル』のEdebugを参照してください。
このデバッガの使い方は、バグを再現する方法が分かっている場合にのみ可能です。再現できない場合は、少なくともエラーメッセージ全体をコピーしてください。
debug-on-quit に non-nil を指定して
C-g
と入力すると、Lispデバッガが起動し、バックトレースが表示されます。このバックトレースはこうした長いループのデバッグに有用ですので、生成できた場合はバグレポートにコピーして記載してください。
Emacs を C-g に反応させることができない場合(例えば inhibit-quit が設定されている場合など)は、Emacs の外部から debug-on-event で指定されたシグナル(デフォルトは
SIGUSR2)を送信して、デバッガに入らせることができます。
ただし、バグの原因を特定したいのであれば、追加情報を収集する際に工夫する必要があります。
例えば、Cレベルのバックトレースだけを送る人が多いですが、それだけではあまり役に立ちません。引数付きの単純なバックトレースでは、GNU Emacs内部で何が起きているかについてほとんど何も伝わらないことが多いです。というのも、バックトレースに列挙される引数の大半はLispオブジェクトへのポインタだからです。これらのポインタの数値自体には全く意味がなく、重要なのはそれらが指すオブジェクトの内容です(そして、その内容の大半自体がポインタとなっています)。
有用な情報を提供するには、Lispオブジェクトの値をLisp記法で表示する必要があります。スタックの下位付近にある複数のスタックフレームにおいて、Lispオブジェクトである各変数についてこれを行ってください。デバッガはそれらを整数として扱うため、どの変数がLispオブジェクトであるかはソースコードで確認してください。
Lisp構文で変数の値を表示するには、まずその値を出力し、次にユーザー定義のGDBコマンド pr
を使用してLispオブジェクトをLisp構文で出力します。(別のデバッガを使用する必要がある場合は、オブジェクトを引数として関数 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 に格納されているディレクトリ名を使用してください。