マルチスレッドのLinuxプロセスで、特定のスレッドが数秒間実行されないように見える問題をデバッグしています。 strace出力を見ると、futexを待機していることがわかりました。
1673109 14:36:28.600329 futex(0x44b8d20、FUTEX_WAIT_PRIVATE、
1673109 14:36:33.221850 <... futex再開>)= 0 <4.621514>
このfutex(0x44b8d20)がユーザー空間で何を指しているのか、つまり、これを内部でfutexを使用しているロック構造にマップする方法を知るにはどうすればよいですか?.
競合するfutexロックのアドレスをすばやく見つけるのに役立つように、単純なsystemtapスクリプトを使用します。アドレスと言うときは、 futex()
syscall の最初の引数を指します。
競合するユーザースペースロックを見つける簡単なシステムタップスクリプトをここからダウンロードできます。
https://sourceware.org/systemtap/examples/process/futexes.stp
システムにsystemtapがインストールされている場合は、
このシステムタップスクリプトを開始するだけです:_stap futexes.stp
_
以前と同じようにstrace
出力をキャプチャします。
Ctrl-Cを実行するだけでシステムタップスクリプトの実行を終了すると、
競合するfutexの出力が表示されます。
最後に、strace出力で、
2番目の引数(操作タイプ)が_FUTEX_WAIT
_であるfutex呼び出しを検索します。
例:futex(0x7f58a31999d0, FUTEX_WAIT, 4508, NULL) = 0
次に、システムタップスクリプト出力の最初の引数を検索できます。
次のようなもの:_ome[4489] lock 0x7f58a31999d0 contended 1 times, 7807 avg us
_
このシステムタップスクリプトを見ると、
プロセス名とプロセス/スレッドIDを適切に出力します。
これにより、探しているものを簡単に見つけることができます。
ただし、systemtapスクリプトを実行すると、実際にはsyscallシステム全体がフックされることに注意してください。
マルチスレッドアプリケーションをデバッグするのは非常に難しいので、ここで私の経験を他の人と共有したいと思います。以下は私のstraceの結果です。
strace: Process 91073 attached
futex(0x7feb282109d0, FUTEX_WAIT, 91074, NULL
私はまだ何をしたかを覚えているので:デバッグ出力をコメントアウトするときに1行を忘れました。これにより、プログラムが途中で機能しなくなります。プロセスはまだ少しCPUを消費しますが、S状態のままです。
unique_lock<mutex> ulk(mut); // Forgot to comment out before the release
// cerr << "I am almost done with the job in this thread\n";
// ulk.unlock();
この場合、タイプミスですが、実際の競合状態でも同じ問題が発生します。