[Bug 14697] New: wineserver: debug events can block completion of queued user APCs

wine-bugs at winehq.org wine-bugs at winehq.org
Wed Jul 30 14:40:36 CDT 2008


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 at winehq.org
        ReportedBy: focht at 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


-- 
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.



More information about the wine-bugs mailing list