Oracle® Developer Studio 12.5: dbx コマンドによるデバッグ

印刷ビューの終了

更新: 2016 年 6 月
 
 

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

dbx は、libthread.so が利用されているかどうかを検出することによって、マルチスレッドプログラムを認識します。プログラムは、-lthread または -mt でコンパイルされることによって明示的に、あるいは -lpthread でコンパイルされることによって暗黙的に libthread.so を使用します。

マルチスレッドプログラムを検出すると、dbx は、/usr/lib にあるスレッドデバッグのための特殊なシステムライブラリである libthread_db.so をロードしようとします。

dbx は同期的に動作するため、いずれかのスレッドまたは軽量プロセス (LWP) が停止すると、その他のスレッドおよび LWP もすべて同様に停止します。 この動作は、「世界停止 (stop the world)」モデルと呼ばれる場合があります。


注 -  マルチスレッドプログラミングと LWP については、Oracle 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 または a l@number は、そのスレッドが指定された LWP にバインドされているか、またはその LWP 上でアクティブであることを示します。つまり、そのスレッドは実際にオペレーティングシステムが実行できます。

  • thr_create に渡されたスレッドの「開始関数」。?() は開始関数が不明であることを示します。

  • スレッド状態。

  • スレッドが現在実行している関数

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

  • t@numberdbx 形式のスレッド ID

  • スレッド状態

  • 単一引用符内のスレッド名

  • スレッドの優先順位を示す番号

スレッドの状態と 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 に所定のシグナルが発生しました。

プロセス同期

この 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@1lookup() の呼び出しで停止すると、dbx は条件の評価を試みたあと、strcmp() を呼び出します。

  • ブレークポイントを設定します。

    stop in lookup

    t@1lookup() の呼び出しで停止したら、次のコマンドを発行します。

    call strcmp(name, "troublesome")

strcmp() を呼び出すときに、dbx は呼び出しの間、すべてのスレッドを再開します。これは、next コマンドでシングルステップを実行しているときの dbx の動作に似ています。この動作は、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() のブレークポイントをヒットしたスレッドのみが再開されます。

    この方法は、次の例のような場合には役立ちません。

  • 条件で再帰的に lookup() を呼び出すため、同じスレッドで lookup() の 2 つ目のブレークポイントが発生した場合

  • 条件を実行するスレッドが生成するか、スリープさせるか、または何らかの方法で、別のスレッドに制御を放棄する場合