http://bugs.winehq.org/show_bug.cgi?id=14697
Summary: wineserver: debug events can block completion of queued user APCs Product: Wine Version: CVS/GIT Platform: PC OS/Version: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: wineserver AssignedTo: wine-bugs@winehq.org ReportedBy: focht@gmx.net
Hello,
consider the following scenario...
A debugger is attached to a debuggee. The debuggee has two threads.
The debugger processes debug events and queries virtual memory info of remote process using VirtualQueryEx in its main loop.
VirtualQueryEx -> NtQueryVirtualMemory -> enqueues APC_VIRTUAL_QUERY user APC for remote process (debuggee). The calling thread is blocked until the APC is completed.
Following is the "good" case:
tid=0009 (debugger process, calling thread, main debugger loop) tid=001a (debuggee thread 1)
--- snip --- .. 0009: queue_apc( thread=(nil), process=0x54, call={APC_VIRTUAL_QUERY,addr=0x7fff0000} ) 001a: *wakeup* signaled=192 cookie=0x7ffdb7b4 0009: queue_apc() = 0 { handle=0x68, self=0 } 0009: select( flags=4, cookie=0x32d30c, signal=(nil), prev_apc=(nil), timeout=infinite, result={}, handles={0x68} ) 0009: select() = PENDING { apc_handle=(nil), timeout=infinite, call={APC_NONE} } 001a: select( flags=4, cookie=0x7ffdb7b4, signal=(nil), prev_apc=(nil), timeout=1c8f097946d2824 (-0.1787600), result={}, handles={} ) 001a: select() = USER_APC { apc_handle=0x68, timeout=1c8f097946d2824 (-0.1787600), call={APC_VIRTUAL_QUERY,addr=0x7fff0000} } 001a: select( flags=4, cookie=0x7ffdb7b4, signal=(nil), prev_apc=0x68, timeout=1c8f097946d2824 (-0.1792110), result={APC_VIRTUAL_QUERY,status=40000002,base=(nil),alloc_base=(nil),size=0,state=0,prot=0,alloc_prot=0,alloc_type=0}, handles={} ) 0009: *wakeup* signaled=0 cookie=0x32d30c 001a: select() = PENDING { apc_handle=(nil), timeout=1c8f097946d2824 (-0.1792110), call={APC_NONE} } 0009: get_apc_result( handle=0x68 ) 0009: get_apc_result() = 0 { result={APC_VIRTUAL_QUERY,status=40000002,base=(nil),alloc_base=(nil),size=0,state=0,prot=0,alloc_prot=0,alloc_type=0} } --- snip ---
Now the interesting one, which ultimately leads to block of calling thread ...
tid=0009 (debugger process, calling thread, main debugger loop) tid=001a (debuggee thread 1) tid=001b (debuggee thread 2)
--- snip --- 0009: continue_debug_event( pid=0019, tid=001a, status=65538 ) 001a: *wakeup* signaled=258 cookie=0x7ffdb7b4 001b: *wakeup* signaled=258 cookie=0x7ffd77b4 0009: continue_debug_event() = 0 .. 0009: read_process_memory( handle=0x54, addr=0x7ffd8000 ) 001a: *signal* signal=19 0009: read_process_memory() = 0 { data= {} } 0009: read_process_memory( handle=0x54, addr=0x7ffd4000 ) 001a: *signal* signal=19 0009: read_process_memory() = 0 { data={} } 0009: queue_apc( thread=(nil), process=0x54, call={APC_VIRTUAL_QUERY,addr=(nil)} ) 001b: *wakeup* signaled=192 cookie=0x7ed44874 0009: queue_apc() = 0 { handle=0x68, self=0 } 001a: load_dll( handle=(nil), base=0x61090000, size=102400, dbg_offset=0, dbg_size=0, name=0x13e468, filename=L"C:\windows\system32\msacm32.dll" ) 001a: *sent signal* signal=10 001b: *sent signal* signal=10 001a: load_dll() = 0 .. 0009: select( flags=4, cookie=0x32d30c, signal=(nil), prev_apc=(nil), timeout=infinite, result={}, handles={0x68} ) 0009: select() = PENDING { apc_handle=(nil), timeout=infinite, call={APC_NONE} } 001a: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context= {...}) 001a: set_thread_context() = 0 { self=1 } 001b: select( flags=4, cookie=0x7ed44874, signal=(nil), prev_apc=(nil), timeout=infinite, result={}, handles={0x4c} ) 001b: select() = USER_APC { apc_handle=0x68, timeout=infinite, call={APC_VIRTUAL_QUERY,addr=(nil)} } 001a: select( flags=4, cookie=0x7ffdb7b4, signal=(nil), prev_apc=(nil), timeout=0, result={}, handles={} ) 001a: select() = PENDING { apc_handle=(nil), timeout=1c8f09794c8b694 (+0.0000000), call={APC_NONE} } 001b: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context= {...}) 001b: set_thread_context() = 0 { self=1 } 001b: select( flags=4, cookie=0x7ffd77b4, signal=(nil), prev_apc=(nil), timeout=0, result={}, handles={} ) 001b: select() = PENDING { apc_handle=(nil), timeout=1c8f09794c90dc4 (+0.0000000), call={APC_NONE} } ... --- snip ---
At this point, tid=0009 (debugger) is blocked forever.
When the APC_VIRTUAL_QUERY user APC is queued, remote thread 001b is selected/destined to carry out the APC.
After thread 001a and 001b woke up, a dynamic library is loaded from thread 001a which results in LOAD_DLL_DEBUG_EVENT dispatched. This initiates the suspension of all threads in the child process (SIGUSR1 is sent for 001a and 001b).
Thread 001a is suspended first, 001b next. The suspension of 001b happens to a time when 001b is about to carry out the APC_VIRTUAL_QUERY.
Meanwhile thread 0009 (calling process) is waiting for APC completion result forever because it's blocked by VirtualQueryEx in debugger loop, unable to receive and process any debug event.
Regards
http://bugs.winehq.org/show_bug.cgi?id=14697
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Version|CVS/GIT |1.1.2
http://bugs.winehq.org/show_bug.cgi?id=14697
--- Comment #1 from Austin English austinenglish@gmail.com 2009-07-21 14:00:57 --- Is this still an issue in current (1.1.26 or newer) wine?
http://bugs.winehq.org/show_bug.cgi?id=14697
--- Comment #2 from Austin English austinenglish@gmail.com 2010-05-26 16:03:02 --- This is your friendly reminder that there has been no bug activity for 6 months. Is this still an issue in current (1.2-rc1 or newer) wine?
http://bugs.winehq.org/show_bug.cgi?id=14697
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution| |FIXED
--- Comment #3 from Anastasius Focht focht@gmx.net 2010-05-26 17:22:38 --- Hello,
unfortunately I don't remember the debuggee I could reproduce this rare signal/APC race ... stupid that I didn't put that info in this bug :-( The debugger was ollydbg 2.x (some alpha version) for sure.
I queried bugzilla with a date range (bug creation date-2 months) and match all bug comments by me but that turned out too many bugs to single out likely candidates.
Let's call it a day ...
Regards
http://bugs.winehq.org/show_bug.cgi?id=14697
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #4 from Alexandre Julliard julliard@winehq.org 2010-05-28 12:50:31 --- Closing bugs fixed in 1.2-rc2.
http://bugs.winehq.org/show_bug.cgi?id=14697
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download Status|CLOSED |UNCONFIRMED URL| |http://www.ollydbg.de/versi | |on2.html Resolution|FIXED |
--- Comment #5 from Anastasius Focht focht@gmx.net 2011-06-14 01:32:38 CDT --- Hello,
reopening, I'm frequently encountering this while debugging (with ollydbg2) ... very annoying.
The problem has already been described in comment #1
Another example backtrace of debugger thread with all the debuggee threads suspended due to dll load or exception event dispatched.
The debugger main loop blocks forever because it can't carry out an APC for NtQueryVirtualMemory in debuggee address space.
--- snip --- Backtrace: =>0 0x68000830 GLIBC_2+0x830() in ld-linux.so.2 (0x0032a6fc) 1 0x7bc81eae NTDLL_wait_for_multiple_objects+0x26c(count=0x1, handles=0x32a9b4, flags=0x4, timeout=(nil), signal_object=0x0(nil)) [/opt/projects/wine/wine-git/dlls/ntdll/sync.c:1124] in ntdll (0x0032a91c) 2 0x7bc81fb1 NtWaitForMultipleObjects+0x67(count=0x1, handles=0x32a9b4, wait_all=0, alertable=0, timeout=(nil)) [/opt/projects/wine/wine-git/dlls/ntdll/sync.c:1162] in ntdll (0x0032a96c) 3 0x7bc81ff7 NtWaitForSingleObject+0x41(handle=0xa4, alertable=0, timeout=(nil)) [/opt/projects/wine/wine-git/dlls/ntdll/sync.c:1171] in ntdll (0x0032a9ac) 4 0x7bc81b2a NTDLL_queue_process_apc+0x185(process=0x70, call=0x32abc8, result=0x32aba0) [/opt/projects/wine/wine-git/dlls/ntdll/sync.c:1070] in ntdll (0x0032aadc) 5 0x7bc92c82 NtQueryVirtualMemory+0x250(process=0x70, addr=0x570000, info_class=MemoryBasicInformation, buffer=0x32acc8, len=0x1c, res_len=0x32ac78) [/opt/projects/wine/wine-git/dlls/ntdll/virtual.c:2191] in ntdll (0x0032ac4c) 6 0x7b87bc83 VirtualQueryEx+0x34(process=0x70, addr=0x570000, info=0x32acc8, len=0x1c) [/opt/projects/wine/wine-git/dlls/kernel32/virtual.c:289] in kernel32 (0x0032ac8c) 7 0x00452464 in ollydbg (+0x52463) (0x0032afb8) 8 0x0044a34b in ollydbg (+0x4a34a) (0x0032c198) 9 0x0044c25d in ollydbg (+0x4c25c) (0x0032f0f0) 10 0x0040e439 in ollydbg (+0xe438) (0x0032fe28) 11 0x004e0f0f in ollydbg (+0xe0f0e) (0x0032fe58) 12 0x00000000 (0x0032fe78) 13 0x7b85fb4f start_process+0x144(peb=0x7ffdf000) [/opt/projects/wine/wine-git/dlls/kernel32/process.c:1087] in kernel32 (0x0032fec8) 14 0x7bc7d9fc call_thread_func+0xb() in ntdll (0x0032fed8) 15 0x7bc7da3a call_thread_entry_point+0x33(entry=0x7b85fa0a, arg=0x7ffdf000) [/opt/projects/wine/wine-git/dlls/ntdll/signal_i386.c:2499] in ntdll (0x0032ffb8) 16 0x7bc53411 start_process+0x25(kernel_start=0x7b85fa0a) [/opt/projects/wine/wine-git/dlls/ntdll/loader.c:2612] in ntdll (0x0032ffe8) 17 0x68026b55 wine_call_on_stack+0x1c() in libwine.so.1 (0x00000000) 0x68000830 GLIBC_2+0x830 in ld-linux.so.2: int $0x80 --- snip ---
One way to work around this is to have the debugger break on dll load events and manually issuing "continue". It seems to "relax" the suspension race.
Regards
http://bugs.winehq.org/show_bug.cgi?id=14697
Alex Bradbury asb@asbradbury.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |asb@asbradbury.org
http://bugs.winehq.org/show_bug.cgi?id=14697
--- Comment #6 from butraxz@gmail.com 2013-12-07 02:23:14 CST --- This ticket has not been updated for over 900 days. Development recommends to check the status on your bug every release or two and let to be known if the bug is still present. If not, mark it fixed. If you are no longer able to put effort to this ticket, you can abandon it.
Is this still an issue with 1.7.8 or higher ?
http://bugs.winehq.org/show_bug.cgi?id=14697
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Summary|wineserver: debug events |OllyDbg 2.x freezes |can block completion of |sometimes during processing |queued user APCs |of debug events (debug | |events can block completion | |of queued user APCs) Ever Confirmed|0 |1
--- Comment #7 from Anastasius Focht focht@gmx.net 2013-12-07 08:59:11 CST --- Hello folks,
yes it's still present with newer Wine versions. Though it seems to depend on the actual debugging use case (complexity, number/order of debugging event). When I encounter it next time, I'll make a note which app.
Refining summary.
$ wine --version wine-1.7.8-128-g37460b6
Regards
https://bugs.winehq.org/show_bug.cgi?id=14697
--- Comment #8 from Anastasius Focht focht@gmx.net --- Hello folks,
still present.
I found another manifestation of the design problem with some native API implemented using APC, now with only a main thread present in debuggee.
Debugger = 32-bit variant of x64_dbg
tid 0x09 = debugger main thread (gui) tid 0x25 = debugger thread (script thread) tid 0x28 = debugger thread (debugger event loop, partially blocking, partially live looping with Sleep)
tid 0x27 = debuggee main thread
Single stepping in debuggee:
--- snip --- 0027: queue_exception_event( first=1, code=80000004, flags=00000000, record=00000000, address=7bc80526, len=0, params={}, context={cpu=x86,eip=7bc80526,esp=0033dca0,ebp=0033dda8,eflags=00200246,cs=0023,ss=002b,ds=002b,es=002b,fs=0063,gs=006b,eax=000000c0,ebx=7bcd3000,ecx=0033dc78,edx=00000000,esi=0033e674,edi=00000000,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00004000,dr7=00000000,...}} ) ... 0027: queue_exception_event() = 0 { handle=0070 } ... 0027: select( flags=2, cookie=0033d07c, timeout=infinite, prev_apc=0000, result={}, data={WAIT,handles={0070}} ) 0027: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 } 0028:Ret KERNEL32.ContinueDebugEvent() retval=00000001 ret=0093ed78 0028:Call KERNEL32.WaitForDebugEvent(0099c6d0,ffffffff) ret=0093cb5f 0028: wait_debug_event( get_handle=1 ) 0028: wait_debug_event() = 0 { pid=0026, tid=0027, wait=0000, event={exception,first=1,exc_code=80000004,flags=00000000,record=00000000,address=7bc80526,params={}} } 0028:Ret KERNEL32.WaitForDebugEvent() retval=00000001 ret=0093cb5f ... --- snip ---
Setting softbp in debuggee using GUI (internally using scripting engine).
PAGE_EXECUTE_READWRITE to prepare for patching opcodes which causes execution of APC.
--- snip --- ... 0025:Call KERNEL32.VirtualProtectEx(00000354,7bc8053a,00000001,00000040,09f0d9a4) ret=00952892 0025: queue_apc( handle=0354, call={APC_VIRTUAL_PROTECT,addr=7bc8053a,size=00000001,prot=40} ) 0027: *wakeup* signaled=192 0025: queue_apc() = 0 { handle=039c, self=0 } 0025: select( flags=2, cookie=09f0d55c, timeout=infinite, prev_apc=0000, result={}, data={WAIT_ALL,handles={039c}} ) 0025: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 } 0027: select( flags=2, cookie=0033d07c, timeout=infinite, prev_apc=0000, result={}, data={WAIT,handles={0070}} ) 0027: select() = USER_APC { timeout=infinite, call={APC_VIRTUAL_PROTECT,addr=7bc8053a,size=00000001,prot=40}, apc_handle=0074 } 0027: select( flags=2, cookie=0033d07c, timeout=infinite, prev_apc=0074, result={APC_VIRTUAL_PROTECT,status=0,addr=7bc80000,size=00001000,prot=20}, data={WAIT,handles={0070}} ) 0028:Ret KERNEL32.Sleep() retval=00000000 ret=007c236c 0025: *wakeup* signaled=0 0028:Call KERNEL32.Sleep(00000001) ret=007c236c 0027: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 } 0025: get_apc_result( handle=039c ) 0025: get_apc_result() = 0 { result={APC_VIRTUAL_PROTECT,status=0,addr=7bc80000,size=00001000,prot=20} } 0025:Ret KERNEL32.VirtualProtectEx() retval=00000001 ret=00952892 --- snip ---
Save opcode and write softbp (int 3):
--- snip --- 0025:Call KERNEL32.ReadProcessMemory(00000354,7bc8053a,09f0d9c1,00000001,09f0d9b0) ret=009528b3 0025: read_process_memory( handle=0354, addr=7bc8053a ) 0027: *signal* signal=19 0025: read_process_memory() = 0 { data={74} } 0025:Ret KERNEL32.ReadProcessMemory() retval=00000001 ret=009528b3 0025:Call KERNEL32.WriteProcessMemory(00000354,7bc8053a,009897ea,00000001,09f0d9b0) ret=009528d8 0025: write_process_memory( handle=0354, addr=7bc8053a, data={cc} ) 0027: *signal* signal=19 0025: write_process_memory() = 0 0025:Ret KERNEL32.WriteProcessMemory() retval=00000001 ret=009528d8 --- snip ---
Make code PAGE_EXECUTE_READ again (causes queuing of APC):
--- snip --- 0025:Call KERNEL32.VirtualProtectEx(00000354,7bc8053a,00000001,00000020,09f0d9a4) ret=00952922 0025: queue_apc( handle=0354, call={APC_VIRTUAL_PROTECT,addr=7bc8053a,size=00000001,prot=20} ) 0027: *wakeup* signaled=192 0025: queue_apc() = 0 { handle=039c, self=0 } 0025: select( flags=2, cookie=09f0d55c, timeout=infinite, prev_apc=0000, result={}, data={WAIT_ALL,handles={039c}} ) 0025: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 } 0027: queue_exception_event( first=1, code=80000003, flags=00000000, record=00000000, address=7bc8053a, len=0, params={}, context={cpu=x86,eip=7bc8053b,esp=0033cfa0,ebp=0033d0a8,eflags=00200246,cs=0023,ss=002b,ds=002b,es=002b,fs=0063,gs=006b,eax=00000000,ebx=7bcd3000,ecx=00000024,edx=0033d054,esi=0033d974,edi=00000000,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00004000,dr7=00000000,...}} ) 0027: queue_exception_event() = 0 { handle=0074 } 0027: select( flags=2, cookie=0033c37c, timeout=infinite, prev_apc=0000, result={}, data={WAIT,handles={0074}} ) 0027: select() = USER_APC { timeout=infinite, call={APC_VIRTUAL_PROTECT,addr=7bc8053a,size=00000001,prot=20}, apc_handle=0078 } 0027: queue_exception_event( first=1, code=80000003, flags=00000000, record=00000000, address=7bc8053a, len=0, params={}, context={cpu=x86,eip=7bc8053b,esp=0033c2a0,ebp=0033c3a8,eflags=00200246,cs=0023,ss=002b,ds=002b,es=002b,fs=0063,gs=006b,eax=00000000,ebx=7bcd3000,ecx=0033c32c,edx=00000000,esi=0033cc74,edi=00000000,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00004000,dr7=00000000,... ... 0028:Ret KERNEL32.Sleep() retval=00000000 ret=007c236c 0027: queue_exception_event() = 0 { handle=007c } 0028:Call KERNEL32.Sleep(00000001) ret=007c236c 0027: select( flags=2, cookie=0033b67c, timeout=infinite, prev_apc=0000, result={}, data={WAIT,handles={007c}} ) 0027: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 } 0028:Ret KERNEL32.Sleep() retval=00000000 ret=007c236c ... 0009:err:ntdll:RtlpWaitForCriticalSection section 0x99d3f0 "?" wait timed out in thread 0009, blocked by 0025, retrying (60 sec) --- snip ---
At this point the debugger and debuggee are stuck.
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'.
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.
$ wine --version wine-1.7.37
Regards
https://bugs.winehq.org/show_bug.cgi?id=14697
Sebastian Lackner sebastian@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |sebastian@fds-team.de
--- Comment #9 from Sebastian Lackner sebastian@fds-team.de --- Created attachment 52592 --> https://bugs.winehq.org/attachment.cgi?id=52592 Hack to disable interruptable waits for running threads
I haven't been able to reproduce this bug yet, but based on the description the attached hack should help.
I assume processing system APCs inside of regular server_select() calls was mainly implemented for performance reasons. However the whole idea seems to be a bit broken by design. We cannot guarantee that an APC will run without interruptions without blocking the signal or sending USR1. Blocking signals is not possible because it would break suspending a thread during a wait. Manually keeping track of the thread state also seems pretty complex. So the best idea I would have would be to remove interruptible waits again, and just always use USR1. :/
https://bugs.winehq.org/show_bug.cgi?id=14697
Sebastian Lackner sebastian@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Attachment #52592|0 |1 is obsolete| |
--- Comment #10 from Sebastian Lackner sebastian@fds-team.de --- Created attachment 52593 --> https://bugs.winehq.org/attachment.cgi?id=52593 Hack to disable interruptable waits for running threads (v2)
Attaching the correct hack helps sometimes.
https://bugs.winehq.org/show_bug.cgi?id=14697
Sebastian Lackner sebastian@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |STAGED CC| |erich.e.hoover@wine-staging | |.com, michael@fds-team.de Staged patchset| |https://github.com/wine-com | |pholio/wine-staging/tree/ma | |ster/patches/ntdll-Wait_Use | |r_APC
https://bugs.winehq.org/show_bug.cgi?id=14697
--- Comment #11 from Sebastian Lackner sebastian@fds-team.de --- I have staged a patch using a better approach. Could you please test if it works?
https://bugs.winehq.org/show_bug.cgi?id=14697
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch
https://bugs.winehq.org/show_bug.cgi?id=14697
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Staged patchset|https://github.com/wine-com |https://github.com/wine-sta |pholio/wine-staging/tree/ma |ging/wine-staging/tree/mast |ster/patches/ntdll-Wait_Use |er/patches/ntdll-Wait_User_ |r_APC |APC
--- Comment #12 from Anastasius Focht focht@gmx.net --- Hello folks,
revisiting still present. Almost 10 year anniversary here _oO_
I encounter it still frequently with vanilla Wine and Ollydbg 2.x when debugging 32-bit apps. Unfortunately I forget with the same frequency to switch to Wine-Staging to validate the problem is gone :|
$ wine --version wine-3.3
Regards
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.
https://bugs.winehq.org/show_bug.cgi?id=14697
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com
--- Comment #14 from Zebediah Figura z.figura12@gmail.com --- As far as I understand, this should have been fixed by https://source.winehq.org/git/wine.git/commitdiff/544fd9504a6b8c646c09d314c1539e4e7b6fb946. Can someone please retest, or give specific instructions for reproducing the bug?
https://bugs.winehq.org/show_bug.cgi?id=14697
Alistair Leslie-Hughes leslie_alistair@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |544fd9504a6b8c646c09d314c15 | |39e4e7b6fb946 Status|STAGED |RESOLVED Resolution|--- |FIXED
--- Comment #15 from Alistair Leslie-Hughes leslie_alistair@hotmail.com --- Fixed by https://source.winehq.org/git/wine.git/?a=commit;h=544fd9504a6b8c646c09d314c...
https://bugs.winehq.org/show_bug.cgi?id=14697
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #16 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 5.2.
https://bugs.winehq.org/show_bug.cgi?id=14697
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL|http://www.ollydbg.de/versi |https://web.archive.org/web |on2.html |/20140209193012/http://olly | |dbg.de/odbg201.zip