DCSIMG
Detecting the STA Thread from GetToSTA - All Your Base Are Belong To Us

All Your Base Are Belong To Us

Mostly .NET internals and other kinds of gory details

Detecting the STA Thread from GetToSTA

When a thread makes a method call through an appropriately marshaled COM proxy that points to a thread in a different STA (Single-Threaded Apartment), ole32.dll kicks in and implements the minute details of marshaling input parameters across the required boundary, waiting for the call to return, and unmarshaling the return value and output parameters.

In a debugger, a thread making a COM call to another STA will have a native call stack similar to the following:

0:002> kb
ChildEBP RetAddr  Args to Child              
... ntdll!ZwWaitForSingleObject+0x15
... KERNELBASE!WaitForSingleObjectEx+0x98
... KERNEL32!WaitForSingleObjectExImplementation+0x75
... KERNEL32!WaitForSingleObject+0x12
00def1d8 7693a819 0056fdc8 ... ole32!GetToSTA+0xad
... ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0x140
00def2e8 7682d0e5 00599ca8 ... ole32!CRpcChannelBuffer::SendReceive2+0xef
... ole32!CAptRpcChnl::SendReceive+0xaf
... ole32!CCtxComChnl::SendReceive+0x95
... ole32!NdrExtpProxySendReceive+0x49
... RPCRT4!NdrpProxySendReceive+0xe
... RPCRT4!NdrClientCall2+0x1a6

The first parameter of ole32!GetToSTA [3] is an internal structure [1] that contains the process ID and thread ID of the STA thread for which the transition is currently waiting. The same structure is also the 7th DWORD field of the first parameter of ole32!CRpcChannelBuffer::SendReceive2 [2].

0:002> dd 00599ca8 L8
00599ca8  7684f3b8 768280dc 00000003 0000002a
00599cb8  00521540 00000000 0056fdc8 00570d08

0:002> dd 0056fdc8 L4
0056fdc8  0056fe48 769468f8 000020b4 00001404

In the second output, the 3rd and 4th DWORDs are the process ID and thread ID, respectively. If the COM call is stuck, you can switch to that process/thread and see what it’s doing—it’s probably in a non-pumping wait, which precludes the COM infrastructure from receiving the incoming call. [0]

References:

[0] .NET Debugging and C++ Debugging Resources
[1] The OXIDEntry structure
[2] Find the STA thread we’re switching to in SendReceive2
[3] Find the STA thread we’re switching to in GetToSTA

Comments

Orion Edwards said:

I am troubleshooting an issue with a .NET application with a hung finalizer thread stuck in a call to GetToSTA. This was invaluable in helping me track it down. Thanks!

# November 28, 2012 3:54 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: