複数のスレッドを使用してアプリケーションをトレースできますか?
-
06-07-2019 - |
質問
私は主にLinuxをターゲットとするGUI指向のデバッガを書いていますが、将来は他のOSへの移植を計画しています。 GUIは常に対話型である必要があるため、さまざまな処理を行うスレッドがいくつかあります。
主に「デバッグイベント」があります。 waitpidが戻るのを待ってループし、受信したイベントを他のスレッドに配信するスレッド。 waitpidにはタイムアウトがないため、他のイベントループと統合して応答を維持するのが非常に難しくなります(waitpidは無期限にハングする可能性があります!)。
この戦略は、これまでのLinuxビルドでうまく機能しました。最近、デバッガースレッドを認識できるようにしようとしています(デバッガー自体ではなく、デバッグされたアプリケーションのスレッドのように)。
したがって、ptraceオプションを設定してクローンイベントを追跡し、上位16ビットが PTRACE_EVENT_CLONE
に設定されているステータスを探します。次に、 PTRACE_GETEVENTMSG
を使用して、新しいスレッドのTIDを取得します。これはすべて、私の小さなテストハーネスアプリケーションでうまく機能します。しかし、何らかの理由で、そのコードを実際のデバッガーに配置すると失敗します。 (「No such process」エラーコードが表示されます)
私に起こったことの1つは、Windowsには、アプリケーションに接続されたスレッドのみがデバッグイベントをリッスンできるというルールがあることです。 Linuxのptraceにも同様の制限がありますか?もしそうなら、なぜ私のコードは他のデバッグイベントで動作しますか?
編集:
最低でもwaitpidは異なるスレッドからの待機をサポートしているようだと、manページは言っています:
Linux 2.4以前では、スレッドは単なる プロセスの特別な場合、および 結果として、1つのスレッドが 別のスレッドの子、たとえ 後者は同じスレッドに属します グループ。ただし、POSIXは規定しています このような機能、およびLinux 2.4以降 スレッドはでき、デフォルトでは 他の子供を待つ 同じスレッドグループ内のスレッド。
これはせいぜいptraceの制限です。
解決
私が知る限り、これは許可されていません。タスクは、アタッチしていないタスクで ptrace
を使用できません。また、タスクは最大で1つの他のタスクによってトレースできるため、各スレッドに一度だけアタッチすることはできません。これは、1つのタスクが別のタスクにアタッチすると、トレースタスクがトレース対象タスクの親になり、各タスクが1つの親しか持つことができないためだと思います。
スレッドは同じプロセスの一部であるため、マルチスレッドトレースを許可する必要があるように見えますが、実装面では、実際にはLinuxカーネルのスレッドとプロセスはあまり区別されていません。スレッドは、たまたまそのリソースの大部分を別のタスクと共有するタスクです。
興味がある場合は、カーネルのptraceのソースコード。具体的には ptrace_check_attach
。によって呼び出されます。ほとんどのリクエストでは sys_ptrace
。ターゲットタスクの親が現在のタスクでない場合、 -ESRCH
(取得しているエラーコードのように聞こえます)を返します。
他のヒント
のLinux固有の部分を実装しているときに、同じ問題(および他の多くの問題!)が発生しました。 Maxine VMデバッガー。デバッガーの1つのスレッドのみがptraceを使用してデバッグ対象を制御できるという推測は正しいです。これを行うには、専用スレッドでptraceをすべて呼び出します。 kenai.com/projects/maxine/sources/maxine/showで入手可能なMaxineソースのLinuxTask.java、linuxTask.h、およびlinuxTask.cファイルを確認すると便利です。