https://bugs.winehq.org/show_bug.cgi?id=14697
Jacek Caban jacek@codeweavers.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |jacek@codeweavers.com
--- Comment #13 from Jacek Caban jacek@codeweavers.com --- (In reply to Anastasius Focht from comment #8)
The problem can be partially attributed to the rather unusual handling of debug events on the debugger side. Instead of having thread 0x28 doing debug event loop continuously using blocking waits, the state machine also has a state where it basically live loops with 'Sleep(1)', polling for variable state changes from other debugger threads until entering the blocking wait again using 'WaitForDebugEvent'.
This sounds similar to what I've seen in VS remote debugger. Commit c1a32a080f982d may be relevant here as well. Before that commit, we could report debug events from different threads instead of blocking, which could cause an inconsistent internal debugger state or races.
When dealing with multi thread debugging, also 649be380b1f0c9d32 and related commits may help in some cases.
During execution of APC_VIRTUAL_PROTECT on the debuggee side, the breakpoint is hit (most likely in area/caller of 'server_select') which causes EXCEPTION_DEBUG_EVENT being sent to debugger. The debugger event thread 0x28 is in a state where it live loops using Sleep(1), unable to handle debug events until the opcode patching sequence finishes in script engine thread 0x25 (return from 'VirtualProtectEx') which blocks debug event delivery/completion. This in turn prevents APC_VIRTUAL_PROTECT from being completed on debuggee side.
This also sounds similar. When we hit a breakpoint during APC execution, that's unrecoverable. Debugger sometimes sets a breakpoint in libc read() implementation, because that's where current CPU context points to. The solution is to report a context captured on entry from PE to native code once we have that separation implemented. Debugger would not set such breakpoints then.