COM, ATL

Single Threaded Apartment(STA)에서 고려해야 할 몇가지 것들

디버그정 2008. 8. 2. 02:17
Single Threaded Apartment(STA)에서 고려해야 할 몇가지 것들

STA component안에서의 Long Blocking Call 회피해야 한다. 이것은 엄밀히 말하면, Deadlock Condition 아니다. 단지, Multiple threads 해당 STA 안에는 존재할 있으며, 단지, 하나의 Thread 처리되도록 Synchronization 되는 구조이므로 하나의 Thread 다른 Apartment Call out 하여 Call return 기다릴 , 그리고, 이것이 불행히도 시간이 오래 걸리는 RPC, Socket 통신과 같은 류라면, 이와 관련 없는 다른 Thread들은 starvation 현상이 발생할 수 있다.  이는 performance 영향을 미칠 수도 있으며, User Hang 현상이라고도 생각할 있다.

 

이러한 경우의 Hang 상태에서 WinDbg 통해 Thread 확인해 보면, 간혹 아래와 같은 Callstack 확인할 있으며, 언급한 것처럼, 해당 STA Component 찾아 Long Blocking Call 없는 확인해야 것이다.

 

0:018> kbL

ChildEBP RetAddr  Args to Child             

01ebea08 7c962124 7c82bad8 0000037c 00000000 ntdll!KiFastSystemCallRet

01ebea0c 7c82bad8 0000037c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc

01ebea7c 7c82ba42 0000037c ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xac

01ebea90 774c54a7 0000037c ffffffff 01ebeb94 kernel32!WaitForSingleObject+0x12

01ebeaac 77589905 000a4c58 000d4c78 00000000 ole32!GetToSTA+0x6f

01ebeacc 77587ed7 01ebeb94 01ebec94 000bcf10 ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+0xcb

01ebebac 77495349 000bcf10 01ebeca4 01ebec94 ole32!CRpcChannelBuffer::SendReceive2+0xc1

01ebec18 774952e1 000bcf10 01ebeca4 01ebec94 ole32!CAptRpcChnl::SendReceive+0xab

01ebec6c 77c8127e 000bcf10 01ebeca4 01ebec94 ole32!CCtxComChnl::SendReceive+0x113

01ebec88 77c813ca 0322b36c 01ebecd0 0600016e rpcrt4!NdrProxySendReceive+0x43

01ebf070 77c811bd 77476298 77479224 01ebf0a8 rpcrt4!NdrClientCall2+0x206

01ebf090 77bf3a12 0000001c 00000003 01ebf0ec rpcrt4!ObjectStublessClient+0x8b

01ebf0a0 77492ee6 0322b36c 01ebf0d8 00000005 rpcrt4!ObjectStubless+0xf

01ebf0ec 77493095 01eb0001 01ebf170 01ebf120 ole32!CStdMarshal::Begin_RemQIAndUnmarshal1+0xaf

01ebf10c 77492fc2 01eb0001 01ebf170 01ebf120 ole32!CStdMarshal::Begin_QueryRemoteInterfaces+0x54

01ebf154 77492f2f 01eb0001 01ebf170 01ebf168 ole32!CStdMarshal::QueryRemoteInterfaces+0x37

01ebf1a0 774a3bde 01ebf168 01ebf170 01ebf1b8 ole32!CStdIdentity::CInternalUnk::QueryMultipleInterfaces+0xda

01ebf1c4 792179c6 0586dad0 01ebf25c 01ebf240 ole32!CStdIdentity::CInternalUnk::QueryInterface+0x33

01ebf1e4 792414ed 0586dad4 01ebf25c 01ebf240 mscorsvr!SafeQueryInterface+0x36

01ebf200 7924193e 0586dad4 01ebf25c 01ebf240 mscorsvr!ComPlusWrapper::SafeQueryInterfaceRemoteAware+0x15

 

0:018> dd 0x000a4c58+8 l2

01ebeab0 00000ab0 000002b7c    < --------- ab0 PID, 2b7c TID

 

Component에서 UI handling 하고 있다면, 이는 STA 놓아야 한다. 만일, MTA안에 놓일 경우에는 UI hang 현상이 발생할 있는 , 이는 MTA기반에 Cross apartment Calling 같은 RPC call 있을 경우에, (이것이 근본적으로 Synchronization Call이므로,) 다른 처리는 모두 Blocking 되며, UI thread 예외는 아닐 것이다. 그러나, STA 놓인다면, 이러한 현상이 발생하지 않는 . 이유는 STA Mechanism 있다. STA에서 cross apartment calling 같은 Call out 발생하는 경우나 동일한 Apartment 존재하는 Multiple clients request Hidden Window OleMainThreadWndClass 의해서 message queuing(pumping)으로 처리되어 synchronization 되므로, cross apartment call 대한 Call return 기다리더라도 Message 처리는 계속 이뤄지며, 이는 UI handling 필요한 Message 역시 예외가 아니기 때문에 MTA 같은 Blocking은 발생하지 않는 . 하지만, 이러한 Mechanism 기인하여 Cross apartment call 의해 call out call return 처리를 위해 동일한 Thread에서 re-entrancy 허용해야만 한다.

 

그러므로, STA에서는 동일한 Thread내에서 re-entrance 허용된다. 이는 또한 문제가 있다. 예를 들어, cross apartment call의 call out 중 Topmost return 아직 처리되지 않은 상태에서 새로운 incoming call 발생할 경우에는 topmost return 바라는 기존의 thread 상태가 변경될 있으며, 이에 따른, 전반적인 process의 흐름에 문제가 생길 있다. 이러한 경우에는 topmost return 완료될 때까지 기다리거나, 아니면, call reject하여 회피할 있는 데, 이를 위해서 IMessageFilter (참조: http://msdn.microsoft.com/en-us/library/ms693740(VS.85).aspx) 이용하여 처리할 수도 있으며, 또한  임의의 lock 필요하다고 생각할 지도 모른다. Message filter 관련하여 MFC에서는 COleMessageFilter 제공하고 있으며 (참조: http://www.pluralsight.com/articlecontent/cpprep1098.htm) 다만, 대표적인 STA Component 개발해 왔던 VB6에서는 지원하지 않는 다는 것이 안타깝다.

 

마지막으로 Cross threads Call 위한 Marshalling Call locking mechanism 비해서 매우 expensive하다.

결국, 이러한 것들은 개발자들로 하여금 STA보다는 MTA 사용을 부추기는 지도 모르지만 MTA 적용된 Application에서의 복잡한 locking 구조에 의한 Deadlock 현상 등은 STA 편리함에 이끌릴지도 모르겠다.

'COM, ATL' 카테고리의 다른 글

COM 기본 개념 ~~ 정리해 보자  (0) 2008.08.08
Process/Thread/Apartment  (0) 2008.08.02
How to Use IMessageFilter  (1) 2008.08.02
Apartment Types  (0) 2008.07.30
COM Message Filters  (0) 2008.07.30
TLS(Thread Local Storage)  (0) 2008.07.30
Safe Initialization and Scripting for ActiveX Controls  (0) 2008.07.29