[Bug 10478] New: wine server get/set thread context doesn' t work correctly if simultaneously used by debugger and debuggee
http://bugs.winehq.org/show_bug.cgi?id=10478 Summary: wine server get/set thread context doesn't work correctly if simultaneously used by debugger and debuggee Product: Wine Version: CVS/GIT Platform: PC OS/Version: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: wine-debug AssignedTo: wine-bugs(a)winehq.org ReportedBy: focht(a)gmx.net Created an attachment (id=9209) --> (http://bugs.winehq.org/attachment.cgi?id=9209) WINEDEBUG=+tid,+server,+win trace of debugging session Hello, while debugging a target with some debugger I experienced severe problems with wine server get/set thread context implementation. It doesn't work correctly if the get/set thread context API is simultaneously used by both, the debugger and the debuggee to manage exception events/control execution transfer. Attached is WINEDEBUG=+tid,+seh,+win trace (don't bother with +win channel output, was for my own purpose). pid=0008, tid=0009 debugger main thread pid=0008, tid=000d debugger debug event loop thread pid=000e, tid=000f debuggee main thread pid=000e, tid=0010 debuggee child thread pid=000e, tid=0011 debuggee child thread pid=000e, tid=0012 debuggee child thread Search for "000d: get_thread_context() = ACCESS_DENIED { self=0, context={} }" in attached log and walk your way back... --- snip --- 000f: queue_exception_event( first=1, record={context={flags=00010007,eax=7b82c455,ebx=7b8ad1e4,ecx=00000000,edx=00004000,esi=00004000,edi=00197430,ebp=0034e5d4,eip=7b841378,esp=0034e570,eflags=00200216,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=a3f67070,dr1=0012e150,dr2=0034eec0,dr3=00000000,dr6=00000006,dr7=00000200,float={00000003,0034e234,33746e49,00000032,00000000,000000f8,0034e280,0034e268,00087510,00198af0,00110014,00000001,00000318,00000000,4d430002,4d430000,00198e18,00000010,00000000,00000000,00000000,4d430003,00000000,00000000,00000000,00000000,00000000,00000000}},rec={code=e06d7363,flags=1,rec=(nil),addr=0x7b841300,params={19930520,34e670,79f9acc4}} ) 000d: *wakeup* signaled=0 cookie=0x616e24c0 0010: *sent signal* signal=10 0011: *sent signal* signal=10 0012: *sent signal* signal=10 000f: queue_exception_event() = 0 { handle=0x244 } --- snip --- Debuggee main thread throws first chance C++ exception (queues event). Ok. --- snip --- 0010: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context={flags=0001001f,eax=00000003,ebx=0000001f,ecx=613516a4,edx=00000008,esi=613516a4,edi=7ffd4000,ebp=613516b8,eip=600007f0,esp=61351670,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff4000,ffffffff,604b434d,035f0073,0034dc34,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,3ffe8000,00000000,80000000,00003ffe,00000000,40038000,00004000}} ) 0010: set_thread_context() = 0 { self=1 } 0011: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context={flags=0001001f,eax=00000003,ebx=00000023,ecx=614624a0,edx=00000008,esi=614624a0,edi=7ffd0000,ebp=614624b4,eip=600007f0,esp=6146246c,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff0100,ffffffff,79e7a66b,06d90073,00000000,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,3ffe8000,00000000,80000000,00003ffd,80000000,40078662,00000100}} ) 0011: set_thread_context() = 0 { self=1 } 0012: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context={flags=0001001f,eax=00000003,ebx=0000003a,ecx=6c101d70,edx=00000008,esi=6c101d70,edi=7ffcc000,ebp=6c101d84,eip=600007f0,esp=6c101d3c,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff0120,ffffffff,79e7a66b,06d90073,00000000,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,00000000,00000000,80000000,00003ffd,60000000,400785bc,00000120}} ) 0012: set_thread_context() = 0 { self=1 } --- snip --- The debuggee child threads get SIGUSR1, suspend themselves (on purpose!). Ok. --- snip --- 000d: wait_debug_event( get_handle=1 ) 000d: wait_debug_event() = 0 { pid=000e, tid=000f, wait=(nil), event={exception,{code=e06d7363,flags=1,rec=(nil),addr=0x7b841300,params={19930520,34e670,79f9acc4},first=1} } .. 000d: continue_debug_event( pid=000e, tid=000f, status=-2147418111 ) 000f: *wakeup* signaled=0 cookie=0x34dfd4 0010: *wakeup* signaled=258 cookie=0x7ffd77b4 0011: *wakeup* signaled=258 cookie=0x7ffd37b4 000d: continue_debug_event() = 0 .. --- snip --- Debugger wakes up and sees first chance C++ exception, decides to pass it to debuggee (resumes execution of threads). Ok. --- snip --- 000f: get_exception_status( handle=0x244 ) 000f: get_exception_status() = 80010001 { context={flags=00010007,eax=7b82c455,ebx=7b8ad1e4,ecx=00000000,edx=00004000,esi=00004000,edi=00197430,ebp=0034e5d4,eip=7b841378,esp=0034e570,eflags=00200216,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=a3f67070,dr1=0012e150,dr2=0034eec0,dr3=00000000,dr6=00000006,dr7=00000200,float={00000003,0034e234,33746e49,00000032,00000000,000000f8,0034e280,0034e268,00087510,00198af0,00110014,00000001,00000318,00000000,4d430002,4d430000,00198e18,00000010,00000000,00000000,00000000,4d430003,00000000,00000000,00000000,00000000,00000000,00000000}} } 0010: get_thread_context( handle=0xfffffffe, flags=00010007, suspend=1 ) 0010: get_thread_context() = 0 { self=1, context={flags=0001001f,eax=00000003,ebx=0000001f,ecx=613516a4,edx=00000008,esi=613516a4,edi=7ffd4000,ebp=613516b8,eip=600007f0,esp=61351670,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff4000,ffffffff,604b434d,035f0073,0034dc34,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,3ffe8000,00000000,80000000,00003ffe,00000000,40038000,00004000}} } 0011: get_thread_context( handle=0xfffffffe, flags=00010007, suspend=1 ) 0011: get_thread_context() = 0 { self=1, context={flags=0001001f,eax=00000003,ebx=00000023,ecx=614624a0,edx=00000008,esi=614624a0,edi=7ffd0000,ebp=614624b4,eip=600007f0,esp=6146246c,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff0100,ffffffff,79e7a66b,06d90073,00000000,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,3ffe8000,00000000,80000000,00003ffd,80000000,40078662,00000100}} } 000d: select( flags=4, cookie=0x616e24c0, signal=(nil), prev_apc=(nil), timeout=+1.0000000, result={}, handles={0xa8} ) 000d: select() = PENDING { apc_handle=(nil), timeout=1c828ffa61af642 (+1.0000000), call={APC_NONE} } 0012: get_thread_context( handle=0xfffffffe, flags=00010007, suspend=1 ) 0012: get_thread_context() = 0 { self=1, context={flags=0001001f,eax=00000003,ebx=0000003a,ecx=6c101d70,edx=00000008,esi=6c101d70,edi=7ffcc000,ebp=6c101d84,eip=600007f0,esp=6c101d3c,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff0120,ffffffff,79e7a66b,06d90073,00000000,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,00000000,00000000,80000000,00003ffd,60000000,400785bc,00000120}} } 000f: get_process_info( handle=0xffffffff ) 000f: get_process_info() = 0 { pid=000e, ppid=0008, exit_code=259, priority=2, affinity=1, peb=0x7ffdf000, start_time=1c828ff9f2037c6 (-10.7374150), end_time=0 } 000f: queue_exception_event( first=1, record={context={flags=00010007,eax=7b82c455,ebx=7b8ad1e4,ecx=00000000,edx=0034ee58,esi=0034ee58,edi=e0434f4d,ebp=0034ee20,eip=7b841378,esp=0034edbc,eflags=00200212,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=02d410d8,dr2=a3f67060,dr3=00000000,dr6=00110000,dr7=00000002,float={0034eaa4,00001302,00198d10,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001,0034eadc,79e783ca,00110000,00000000,79e783e6,a3f67cf4,00000001,00197430,00000000,00000008,00000000,0034eb14,7a3296dc,ffffffff,79e783e6,79e7839d,00110000}},rec={code=e0434f4d,flags=1,rec=(nil),addr=0x7b841300,params={80004002}} ) --- snip --- Main debuggee thread SEH evaluates first chance exception and converts it internally to CLR exception, throwing again. --- snip --- 0010: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context={flags=0001001f,eax=00000003,ebx=0000001f,ecx=613516a4,edx=00000008,esi=613516a4,edi=7ffd4000,ebp=613516b8,eip=600007f0,esp=61351670,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff4000,ffffffff,604b434d,035f0073,0034dc34,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,3ffe8000,00000000,80000000,00003ffe,00000000,40038000,00004000}} ) 0010: set_thread_context() = 0 { self=1 } 0011: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context={flags=0001001f,eax=00000003,ebx=00000023,ecx=614624a0,edx=00000008,esi=614624a0,edi=7ffd0000,ebp=614624b4,eip=600007f0,esp=6146246c,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff0100,ffffffff,79e7a66b,06d90073,00000000,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,3ffe8000,00000000,80000000,00003ffd,80000000,40078662,00000100}} ) 0011: set_thread_context() = 0 { self=1 } 0012: set_thread_context( handle=0xfffffffe, flags=00010007, suspend=1, context={flags=0001001f,eax=00000003,ebx=0000003a,ecx=6c101d70,edx=00000008,esi=6c101d70,edi=7ffcc000,ebp=6c101d84,eip=600007f0,esp=6c101d3c,eflags=00200293,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={ffff037f,ffff0120,ffffffff,79e7a66b,06d90073,00000000,0000007b,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,3fff8000,00000000,80000000,00003ffe,00000000,00000000,00000000,80000000,00003ffd,60000000,400785bc,00000120}} ) 0012: set_thread_context() = 0 { self=1 } --- snip --- The debuggee child threads get SIGUSR1, suspend themselves again (on purpose!). Ok. --- snip --- 000d: suspend_thread( handle=0xd4 ) 000d: suspend_thread() = 0 { count=0 } 000d: suspend_thread( handle=0xd8 ) 000d: suspend_thread() = 0 { count=0 } 000d: suspend_thread( handle=0xf8 ) 000d: suspend_thread() = 0 { count=0 } 000d: get_thread_context( handle=0xbc, flags=0001003f, suspend=0 ) 000f: *signal* signal=19 000d: get_thread_context() = 0 { self=0, context={flags=0001003f,eax=7b82c455,ebx=7b8ad1e4,ecx=00000000,edx=0034ee58,esi=0034ee58,edi=e0434f4d,ebp=0034ee20,eip=7b841378,esp=0034edbc,eflags=00200212,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,float={0034eaa4,00001302,00198d10,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001,0034eadc,79e783ca,00110000,00000000,79e783e6,a3f67cf4,00000001,00197430,00000000,00000008,00000000,0034eb14,7a3296dc,ffffffff,79e783e6,79e7839d,00110000}} } 000d: read_process_memory( handle=0xb8, addr=0x7b841378 ) 000f: *signal* signal=19 000d: read_process_memory() = 0 { data={8b} } 000d: resume_thread( handle=0xbc ) 000d: resume_thread() = 0 { count=1 } 000d: resume_thread( handle=0xd4 ) 000d: resume_thread() = 0 { count=1 } 000d: resume_thread( handle=0xd8 ) 000d: resume_thread() = 0 { count=1 } 000d: resume_thread( handle=0xf8 ) 000d: resume_thread() = 0 { count=1 } 000d: continue_debug_event( pid=000e, tid=000f, status=-2147418111 ) 000f: *wakeup* signaled=0 cookie=0x34e824 0010: *wakeup* signaled=258 cookie=0x7ffd77b4 0011: *wakeup* signaled=258 cookie=0x7ffd37b4 0012: *wakeup* signaled=258 cookie=0x7ffcf7b4 000d: continue_debug_event() = 0 --- snip --- Debugger wakes up again, now seeing the CLR exception. Debugger suspends debuggee threads - although unnecessary due to debugging event before = already suspended. This exception type is unhandled, main debuggee thread receives SIGSTOP. Execution of debuggee threads resumed. --- snip --- 000f: get_exception_status( handle=0x244 ) 000f: get_exception_status() = 80010001 { context={flags=00010007,eax=7b82c455,ebx=7b8ad1e4,ecx=00000000,edx=0034ee58,esi=0034ee58,edi=e0434f4d,ebp=0034ee20,eip=7b841378,esp=0034edbc,eflags=00200212,cs=0073,ds=007b,es=007b,fs=0033,gs=003b,dr0=00000000,dr1= .. 000f: *killed* exit_code=0 --- snip --- Debuggee main thread dies. Ok. --- snip --- 000d: wait_debug_event( get_handle=1 ) 000d: wait_debug_event() = 0 { pid=000e, tid=000f, wait=(nil), event={exit_thread,code=0} } 000d: suspend_thread( handle=0xd4 ) 000d: suspend_thread() = 0 { count=0 } 000d: suspend_thread( handle=0xd8 ) 000d: suspend_thread() = 0 { count=0 } 000d: suspend_thread( handle=0xf8 ) 000d: suspend_thread() = 0 { count=0 } 000d: get_thread_context( handle=0xbc, flags=0001003f, suspend=0 ) 000d: get_thread_context() = ACCESS_DENIED { self=0, context={} } 000d: get_thread_context( handle=0xbc, flags=0001003f, suspend=0 ) 000d: get_thread_context() = ACCESS_DENIED { self=0, context={} } 000d: get_thread_context( handle=0xbc, flags=0001003f, suspend=0 ) 000d: get_thread_context() = ACCESS_DENIED { self=0, context={} } 000d: get_thread_context( handle=0xbc, flags=0001003f, suspend=0 ) 000d: get_thread_context() = ACCESS_DENIED { self=0, context={} } 000d: get_thread_context( handle=0xbc, flags=0001003f, suspend=0 ) 000d: get_thread_context() = ACCESS_DENIED { self=0, context={} } 000d: read_process_memory( handle=0xb8, addr=(nil) ) 000d: read_process_memory() = ACCESS_DENIED { data={} } .. --- snip --- Debugger wakes up, sees debuggee (main) thread termination event. Suspends remaining debuggee threads - although unnecessary due to debugging event before = already suspended. Now the problem: the debugger can't get the thread context of any debuggee threads nor process memory anymore after this point. Basically dead end here... The reason is the way server/thread.c/get_thread_context() and server/thread.c/set_thread_context() handles thread->context and thread->suspend_context data ("self" vs. "foreign" threads) child threads "self": set_thread_context() -> suspend == 1 -> thread->suspend_context filled get_thread_context(): req->suspend == 1 && thread == current && thread->suspend_context --- snip --- if (thread->context == thread->suspend_context) thread->context = NULL; set_reply_data_ptr( thread->suspend_context, sizeof(CONTEXT) ); thread->suspend_context = NULL; --- snip --- Which resets the context and suspend context data. Next time when the debugger itself tries to query the thread context of already suspended debuggee child threads it will obviously fail: "foreign" debugger thread: get_thread_context() -> suspend == 0 --- snip --- else if (thread != current && !thread->context) { /* thread is not suspended, retry (if it's still running) */ if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED ); else set_error( STATUS_PENDING ); } --- snip --- I guess this is an oversight, a behavior not really intended? Regards -- Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=10478 --- Comment #1 from Austin English <austinenglish(a)gmail.com> 2008-06-04 14:26:54 --- Is this still an issue in 1.0-rc3? -- Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email Do not reply to this email, post in Bugzilla using the above URL to reply. ------- You are receiving this mail because: ------- You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=10478 Austin English <austinenglish(a)gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution| |ABANDONED --- Comment #2 from Austin English <austinenglish(a)gmail.com> 2008-12-02 05:29:31 --- Abandoned. -- Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email Do not reply to this email, post in Bugzilla using the above URL to reply. ------- You are receiving this mail because: ------- You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=10478 Austin English <austinenglish(a)gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED --- Comment #3 from Austin English <austinenglish(a)gmail.com> 2008-12-02 05:30:33 --- Closing. -- Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email Do not reply to this email, post in Bugzilla using the above URL to reply. ------- You are receiving this mail because: ------- You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=10478 Austin English <austinenglish(a)gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Version|CVS/GIT |unspecified -- Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email Do not reply to this email, post in Bugzilla using the above URL to reply. ------- You are receiving this mail because: ------- You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=10478 Anastasius Focht <focht(a)gmx.net> changed: What |Removed |Added ---------------------------------------------------------------------------- Version|unspecified |0.9.49. --- Comment #4 from Anastasius Focht <focht(a)gmx.net> 2011-10-12 04:10:46 CDT --- Hello, filling/correcting fields ... Aww, abandoned gems .. wish I provided more info at the time ;-) Regards -- Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email Do not reply to this email, post in Bugzilla using the above URL to reply. ------- You are receiving this mail because: ------- You are watching all bug changes.
participants (1)
-
wine-bugs@winehq.org