ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
![]() |
Oracle Solaris Studio 12.3: dbx コマンドによるデバッグ Oracle Solaris Studio 12.3 Information Library (日本語) |
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 を参照)
単一引用符内のスレッド名
スレッドの優先順位を示す番号
表 11-1 スレッドの状態と 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 つ目のブレークポイントが発生した場合
条件を実行するスレッドが生成するか、スリープさせるか、または何らかの方法で、別のスレッドに制御を放棄する場合