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

マルチスレッドデバッグについて

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)

ネイティブコードに対して、情報の各行の内容は次のとおりです。

Java コードでは、情報の各行は次で構成されています。

表 11–1 スレッドの状態と LWP の状態

スレッドの状態と LWP の状態  

内容の説明  

中断 

スレッドは明示的に中断されています。 

実行可能 

スレッドは実行可能であり、コンピューティング可能なリソースとして LWP を待機しています。 

ゾンビ 

切り離されたスレッドが存在する場合 (thr_exit())、次の関数を使用して再接続するまではそのスレッドはゾンビ状態にあります。thr_join()THR_DETACHED は、スレッドの生成時に指定されたフラグです (thr_create())。非結合のスレッドは、再実行されるまでゾンビ状態です。

syncobj でスリープ中

スレッドは所定の同期オブジェクトでブロックされています。libthreadlibthread_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 つのシナリオを次に示します。

strcmp() を呼び出すと、dbx は呼び出しの間、すべてのスレッドを再開することがありますが、これは dbx の動作 (next コマンドを使用して、シングルステップ実行をする場合) に似ています。この動作は、t@1 のみを再開すると、strcmp() が別のスレッドによって所有されているロックを奪取しようと試みた場合に、デッドロックが発生する可能性があるためです。

この場合にすべてのスレッドを再開することの欠点は、strcmp() の呼び出し中に lookup() のブレークポイントにヒットして、dbxt@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() のブレークポイントをヒットしたスレッドのみが再開されます。

この方法は、次のような状況では無効です。