dbx は、マルチスレッドプログラムを検出すると、libthread_db.so の dlopen を試行します。これは、/usr/lib にあるスレッドデバッグ用の特別なシステムライブラリです。
dbx は同期的に動作します。つまり、スレッドか軽量プロセス (LWP) のいずれかが停止すると、ほかのスレッドおよび LWP もすべて自動的に停止します。この動作は、「世界停止 (stop the world)」モデルと呼ばれる場合があります。
マルチスレッドプログラミングと LWP については、『Solaris マルチスレッド のプログラミング』を参照してください。
dbx では、次のスレッド情報を入手できます。
(dbx) threads t@1 a l@1 ?() running in main() t@2 ?() asleep on 0xef751450 in_swtch() t@3 b l@2 ?() running in sigwait() t@4 consumer() asleep on 0x22bb0 in _lwp_sema_wait() *>t@5 b l@4 consumer() breakpoint in Queue_dequeue() t@6 b l@5 producer() running in _thread_start() (dbx) |
ネイティブコードに対して、情報の各行の内容は次のとおりです。
* (アスタリスク) は、ユーザーの注意を必要とするイベントがこのスレッドで発生したことを示します。通常は、ブレークポイントに付けられます。
アスタリスクの代わりに 'o' が示される場合は、dbx 内部イベントが発生しています。
> (矢印) は現在のスレッドを示します。
t@number はスレッド ID であり、特定のスレッドを指します。number は、thr_create が返す thread_t の値になります。
b l@number はそのスレッドが指定の LWP に結合されていることを表し、a l@number はそのスレッドがアクティブであることを表します。すなわちそのスレッドはオペレーティングシステムにて実行可能です。
thr_create に渡されたスレッドの開始関数。?() は開始関数が不明であることを示します。
スレッド状態 (スレッド状態の詳細については、表 11–1 を参照)
スレッドが現在実行している関数
Java コードでは、情報の各行は次で構成されています。
t@number は dbx スタイルスレッド ID を示します。
スレッド状態 (スレッド状態の詳細については、表 11–1 を参照)
単一引用符内のスレッド名
スレッドの優先順位を示す番号
スレッドの状態と LWP の状態 |
内容の説明 |
---|---|
中断 |
スレッドは明示的に中断されています。 |
実行可能 |
スレッドは実行可能であり、コンピューティング可能なリソースとして LWP を待機しています。 |
ゾンビ |
切り離されたスレッドが存在する場合 (thr_exit())、次の関数を使用して再接続するまではそのスレッドはゾンビ状態にあります。thr_join()THR_DETACHED は、スレッドの生成時に指定されたフラグです (thr_create())。非結合のスレッドは、再実行されるまでゾンビ状態です。 |
syncobj でスリープ中 |
スレッドは所定の同期オブジェクトでブロックされています。libthread と libthread_db によるサポートレベルにより、syncobj が伝える情報は単純な 16 進アドレスになったり、より詳細な内容になります。 |
アクティブ |
LWP でスレッドがアクティブですが、dbx は LWP をアクセスできません。 |
未知 |
dbx では状態を判定できません。 |
lwpstate |
結合スレッドやアクティブスレッドの状態に、LWP の状態が関連付けられています。 |
実行中 |
LWP が実行中でしたが、ほかの LWP と同期して停止しました。 |
システムコール num |
所定のシステムコール番号の入口で LWP が停止しました。 |
システムコール num 戻り |
所定のシステムコール番号の出口で LWP が停止しました。 |
ジョブコントロール |
ジョブコントロールにより、LWP が停止しました。 |
LWP 中断 |
LWP がカーネルでブロックされています。 |
シングル中断 |
LWP により、1 ステップが終了しました。 |
ブレークポイント |
LWP がブレークポイントに達しました。 |
障害 num |
LWP に所定の障害番号が発生しました。 |
シグナル name |
LWP に所定のシグナルが発生しました。 |
プロセス sync |
この LWP が所属するプロセスの実行が開始しました。 |
LWP 終了 |
LWP は終了プロセス中です。 |
表示コンテキストを別のスレッドに切り替えるには、thread コマンドを使用します。この構文は次のとおりです。
thread [-blocks] [-blockedby] [-info] [-hide] [-unhide] [-suspend] [-resume] thread_id |
thread |
スレッド thread_id に切り替えるには、次のように入力します。
thread thread_id |
thread コマンドの詳細については、「thread コマンド」を参照してください。
スレッドリストを表示するには、threads コマンドを使用します。この構文は次のとおりです。
threads [-all] [-mode [all|filter] [auto|manual]] |
既知のスレッドすべてのリストを表示するには、次のように入力します。
threads |
通常は表示されないスレッド (ゾンビ) などを表示するには、次のように入力します。
threads -all |
スレッドリストについては、「スレッド情報」を参照してください。
threads コマンドの詳細については、「threads コマンド」を参照してください。
プログラムの実行を再開するには、cont コマンドを使用します。プログラム現在、スレッドは同期ブレークポイントを使用して、すべてのスレッドが実行を再開するようにしています。
ただし、シングルスレッドは、call コマンドに -resumeone オプションを付けて使用することにより再開できます (「call コマンド」を参照)。
多数のスレッドが関数 lookup() を呼び出すマルチスレッドアプリケーションをデバッグする場合の 2 つのシナリオを次に示します。
条件付きブレークポイントを設定します。
stop in lookup -if strcmp(name, "troublesome") == 0 |
t@1 が lookup() の呼び出しで停止すると、 dbx は条件の評価を試み、strcmp() を呼び出します。
ブレークポイントを設定します。
stop in lookup |
t@1 が lookup() の呼び出しで停止したら、次のコマンドを発行します。
call strcmp(name, "troublesome") |
strcmp() を呼び出すと、dbx は呼び出しの間、すべてのスレッドを再開することがありますが、これは dbx の動作 (next コマンドを使用して、シングルステップ実行をする場合) に似ています。この動作は、t@1 のみを再開すると、strcmp() が別のスレッドによって所有されているロックを奪取しようと試みた場合に、デッドロックが発生する可能性があるためです。
この場合にすべてのスレッドを再開することの欠点は、strcmp() の呼び出し中に lookup() のブレークポイントにヒットして、dbx が t@2 などのほかのスレッドを処理できないことです。次のような警告が表示されます。
イベント無限ループにより次のハンドラ中でイベントの取りこぼしが起きます。
イベントの再入 第 1 イベント BPT(VID 6、TID 6、PC echo+0x8) 第 2 イベント BPT(VID 10、TID 10、PC echo+0x8) 以下のハンドラはイベントを処理しません。
そのような場合は、条件式で呼び出された関数が相互排他ロックを奪取しないことが確実であれば、-resumeone イベント修飾子を使用して、dbx に t@1 のみを再開させることができます。
stop in lookup -resumeone -if strcmp(name, "troublesome") == 0 |
strcmp() を評価するために、lookup() のブレークポイントをヒットしたスレッドのみが再開されます。
この方法は、次のような状況では無効です。
条件で再帰的に lookup() を呼び出すため、同じスレッドで lookup() の 2 つ目のブレークポイントが発生した場合
条件を実行するスレッドが生成するか、スリープさせるか、または何らかの方法で、別のスレッドに制御を放棄する場合