dbx は、libthread.so が利用されているかどうかを検出することによって、マルチスレッドプログラムを認識します。プログラムは、-lthread または -mt でコンパイルされることによって明示的に、あるいは -lpthread でコンパイルされることによって暗黙的に libthread.so を使用します。
マルチスレッドプログラムを検出すると、dbx は、/usr/lib にあるスレッドデバッグのための特殊なシステムライブラリである libthread_db.so をロードしようとします。
dbx は同期的に動作するため、いずれかのスレッドまたは軽量プロセス (LWP) が停止すると、その他のスレッドおよび LWP もすべて同様に停止します。 この動作は、「世界停止 (stop the world)」モデルと呼ばれる場合があります。
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 または a l@number は、そのスレッドが指定された LWP にバインドされているか、またはその LWP 上でアクティブであることを示します。つまり、そのスレッドは実際にオペレーティングシステムが実行できます。
thr_create に渡されたスレッドの「開始関数」。?() は開始関数が不明であることを示します。
スレッド状態。
スレッドが現在実行している関数
Java コードでは、情報の各行は次で構成されています。
t@number、dbx 形式のスレッド ID
スレッド状態
単一引用符内のスレッド名
スレッドの優先順位を示す番号
スレッドは明示的に中断されています。
スレッドは実行可能であり、コンピューティング可能なリソースとして LWP を待機しています。
切り離されたスレッドが終了すると (thr_exit))、そのスレッドは、thr_join() を使用して再度参加させられるまでゾンビ状態にあります。THR_DETACHED は、スレッドの作成時 (thr_create()) に指定されたフラグです。非結合のスレッドは、再実行されるまでゾンビ状態です。
スレッドは所定の同期オブジェクトでブロックされています。libthread と libthread_db によって提供されるサポートレベルに応じて、syncobj は単なる 16 進数のアドレスになったり、より詳細な情報になったりします。
スレッドは LWP 上でアクティブですが、dbx がその LWP にアクセスできません。
dbx では状態を判定できません。
結合スレッドやアクティブスレッドの状態に、LWP の状態が関連付けられています。
LWP が実行中でしたが、ほかの LWP と同期して停止しました。
所定のシステムコール番号の入口で LWP が停止しました。
所定のシステムコール番号の出口で LWP が停止しました。
ジョブコントロールにより、LWP が停止しました。
LWP がカーネルでブロックされています。
LWP により、1 ステップが終了しました。
LWP がブレークポイントに達しました。
LWP に所定の障害番号が発生しました。
LWP に所定のシグナルが発生しました。
この LWP が所属するプロセスの実行が開始しました。
LWP は終了プロセス中です。
表示コンテキストを別のスレッドに切り替えるには、thread コマンドを使用します。 この構文は次のとおりです。
thread [-blocks] [-blockedby] [-info] [-hide] [-unhide] [-suspend] [-resume] thread_id
thread
スレッド thread-ID に切り替えるには、次のように入力します。
thread thread-ID
詳細については、thread コマンドを参照してください。
スレッドリストを表示するには、threads コマンドを使用します。この構文は次のとおりです。
threads [-all] [-mode [all|filter] [auto|manual]]
既知のすべてのスレッドのリストを出力するには、次のように入力します。
threads
通常は出力されないスレッド (ゾンビ) を出力するには、次のように入力します。
threads -all
スレッドリストについては、スレッド情報を参照してください。
threads コマンドの詳細については、threads コマンドを参照してください。
プログラムの実行を再開するには cont コマンドを使用します。 現在、スレッドは同期ブレークポイントを使用して、すべてのスレッドが実行を再開するようにしています。ただし、–resumeone オプションを指定して call コマンドを使用することにより、1 つのスレッドを再開できます。
多数のスレッドが関数 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 は呼び出しの間、すべてのスレッドを再開します。これは、next コマンドでシングルステップを実行しているときの dbx の動作に似ています。この動作は、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 つ目のブレークポイントが発生した場合
条件を実行するスレッドが生成するか、スリープさせるか、または何らかの方法で、別のスレッドに制御を放棄する場合