私は Windows デバッガーを作成しているので、通常の ContinueDebugEvent/WaitForDebugEvent ループがあります。
while (true)
{
ContinueDebugEvent(hTargetProcessId, hTargetThreadId, lastDebugResult);
WaitForDebugEvent(&evt, INFINITE);
...
hTargetThreadId = evt.dwThreadId;
}
これは問題なく動作しますが、デバッグ中に特定のスレッドを実行する機能を必要とする機能を追加中です。これを行うには、次のように、興味のないすべてのスレッドを一時停止します (簡潔にするためにコードのロードを省略しました - これが十分に明確であることを願っています!):
while (true)
{
if (onlyACertainThread)
{
for (int n=0; n<threadcount; n++)
if(threads[n] != certainThread)
SuspendThread(threads[n]);
}
ContinueDebugEvent(hTargetProcessId, hTargetThreadId, lastDebugResult);
WaitForDebugEvent(&evt, INFINITE);
if (onlyACertainThread)
{
for (int n=0; n<threadcount; n++)
if(threads[n] != certainThread)
ResumeThread(threads[n]);
}
...
(code to add to 'threads', update threadcount, decide if we want to restrict to a certain thread, etc)
...
hTargetThreadId = evt.dwThreadId;
}
ただし、間違ったスレッドからのデバッグ イベントが頻繁に表示されます。例えば:
- スレッド A が実行中です
- スレッド B を監視することを決定します。スレッド A を一時停止し、continue/waitfordebugevent(.. A.pid..) を呼び出します
- スレッド A からデバッグ通知 (ブレークポイント、例外) を取得します。
私が欲しいのは、最後のステップが「Bから通知を受け取る」ことです。動作しない WaitForDebugEvent(..B.pid..) を呼び出してみました。
これは予想される動作ですか?
私の疑いでは、スレッドの一時停止/再開カウンターは、スレッドがスケジュールされているときにのみカーネルによって監視されます。つまり、タイムスライスの最後です。これにより、スレッド A は現在のタイムスライスがアップするまで実行を続けます。誰でもこの考えを確認/否定できますか? もしそうなら..どうすれば回避できますか?現時点での私の最善のアイデアは、スレッドを中断した後に Sleep(0) の人為的な呼び出しを「注入」することですが、必要がない限り、実際にはそうしたくありません!
違いがあるとすれば、私が実行しているマシンはシングルスレッドの XP ボックスです。