Oracle Solaris Studio 12.2: dbx コマンドによるデバッグ

第 14 章 シグナルの処理

この章では、dbx を使用してシグナルを処理する方法を説明します。dbx は、catch というブレークポイントコマンドをサポートします。catch コマンドは、catch リストに登録されているシステムシグナルのいずれかが検出された場合にプログラムを停止するよう dbx に指示します。

また、dbx コマンド contstepnext は、オプション -sig signal_name をサポートします。このオプションを使用すると、実行を再開したプログラムに対し、cont -sig コマンドで指定したシグナルを受信した場合の動作をさせることができます。

この章は次の各節から構成されています。

シグナルイベントについて

デバッグ中のプロセスにシグナルが送信されると、そのシグナルはカーネルによって dbx に送られます。通常、このことはプロンプトによって示されますが、そこでは次の 2 つの操作から 1 つを選択してください。

図 14–1 SIGINT シグナルの阻止と取り消し

シグナルが転送される通常のケースと、dbx によってシグナルが阻止されキャンセルされるデバッグ中のケース。

さらに、特定のシグナルを頻繁に受信する場合、そのシグナルを表示させずに受信したシグナルを dbx が自動的に転送するように設定できます。次のように入力します。


ignore signal # “ignore”

前述の操作をしてもシグナルはプロセスに送信されます。シグナルがデフォルト設定で、このように自動送信されるようになっているからです (ignore コマンド」を参照)。

システムシグナルを捕獲する

デフォルトのシグナル捕獲リスト (catch リスト) には、33 種類の検出可能なシグナルのうちの 22 種類が含まれています (これらの数はオペレーティングシステムとそのバージョンによって異なります)。デフォルトの catch リストは、リストにシグナルを追加したり削除したりすることによって変更できます。


注 –

dbx が受け付けるシグナル名のリストは、dbx がサポートするバージョンの Solaris オペレーティング環境によってサポートされているすべてを含みます。したがって、dbx は、ユーザーが実行している Solaris オペレーティング環境のバージョンでサポートされていないシグナルを受け付ける場合があります。たとえば、dbx は、ユーザーが Solaris 7 OS を実行していても、Solaris 9 OS によってサポートされているシグナルを受け付けます。実行している Solaris OS でサポートされているシグナルのリストについては、signal(3head) マニュアルページを参照してください。


現在捕獲されているシグナルのリストを調べるには、シグナルの引数を指定せずに、次のように入力します。


(dbx) catch

プログラムで検出された場合でも、現在無視されているシグナルのリスト (ignore リスト) を調べるには、シグナル名の引数を指定せずに、次のように入力します。


(dbx) ignore

デフォルトの catch リストと ignore リストを変更する

どのシグナルでプログラムを停止するかは、2 つのリストの間でシグナル名を移動することによって制御します。シグナル名を移動するには、一方のリストに現在表示されているシグナル名を、もう一方のリストに引数として渡します。

たとえば、QUIT シグナルと ABRT シグナルを catch リストから ignore リストに移動するには、次のように入力します。


(dbx) ignore QUIT ABRT

FPE シグナルをトラップする (Solaris プラットフォームのみ)

浮動小数点の計算が必要なコードを扱っている場合には、プログラム内で発生した例外をデバッグしなければならないことがよくあります。オーバーフローやゼロ除算などの浮動小数点例外が発生すると、例外を起こした演算の結果としてシステムが「適正な」答えを返します。適正な答えが返されることで、プログラムは正常に実行を続けることができます (Solaris OS は、IEEE 標準のバイナリ浮動小数点演算定義の、例外に対する「適正 (reasonable) な」答えを実装しています)。

浮動小数点例外に対して適正な答えを返すため、例外によって自動的に SIGFPE シグナルが生成されることはありません。例外の場合 (ゼロで整数を割ると整数がオーバーフローする場合など) は、デフォルトでは SIGFPE シグナルをトリガーします。

例外の原因を見つけ出すためには、例外によって SIGFPE シグナルが生成されるように、トラップハンドラをプログラム内で設定する必要があります (トラップハンドラの例については、ieee_handler(3m) コマンドのマニュアルページを参照)。

トラップを有効にするには、次のコマンド等を利用します。

ieee_handler コマンドを使用してトラップハンドラを設定すると、ハードウェア浮動小数点状態レジスタ内のトラップ許可マスクがセットされます。このトラップ許可マスクにより、実行中に例外が発生すると SIGFPE シグナルが生成されます。

トラップハンドラ付きのプログラムをコンパイルしたあと、そのプログラムを dbx に読み込んでください。ここで、SIGFPE シグナルが捕獲されるようにするには、dbx のシグナル捕獲リスト (catch リスト) に FPE を追加する必要があります。


(dbx) catch FPE

FPE はデフォルトでは ignore リストに含まれています。

例外の発生場所の判定

FPE を catch リストに追加後、dbx でプログラムを実行します。トラップしている例外が発生すると SIGFPE シグナルが生成され、dbx はプログラムを停止します。ここで、呼び出しスタックを (dbx コマンド where を使用して) トレースすることにより、プログラムの何行目で例外が発生したかを調べることができます (where コマンド」参照)。

例外処理の原因追求

例外処理の原因を調べるには、regs -f コマンドを実行して浮動小数点状態レジスタ (FSR) を表示します。このレジスタで、発生した例外処理 (aexc) フィールドと現在の例外処理 (cexc) フィールドの内容を確認します。このフィールドには次のような浮動小数点例外条件が格納されています。

浮動小数点状態レジスタの詳細については、『SPARC アーキテクチャーマニュアルバージョン 8』(V9 の場合はバージョン 9) を参照してください。説明と例については、『数値演算ガイド』を参照してください。

プログラムにシグナルを送信する

dbx コマンド cont は、オプション -sig signal をサポートします。このオプションを使用すると、実行を再開したプログラムに対し、指定したシステムシグナル signal を受信した場合の動作をさせることができます。

たとえば、プログラムに SIGINT (^C) の割り込みハンドラが含まれている場合、^C を入力することによって、アプリケーションを停止し、dbx に制御を返すことができます。ここで、プログラムの実行を継続するときにオプションなしの cont コマンドを使用すると、割り込みハンドラは実行されません。割り込みハンドラを実行するためには、プログラムに SIGINT シグナルを送信する必要があります。次のコマンドを使用します。


(dbx) cont -sig int

stepnextdetach コマンドも、-sig オプションを指定できます。

シグナルの自動処理

イベント管理コマンドでは、シグナルをイベントとして処理することもできます。次の 2 つのコマンドの結果は同じになります。


(dbx) stop sig signal
(dbx) catch signal

プログラミング済みのアクションを関連付ける必要がある場合、シグナルイベントがあると便利です。


(dbx) when sig SIGCLD {echo Got $sig $signame;}

この場合は、まず SIGCLD を ignore リストに必ず移動してください。


(dbx) ignore SIGCLD