배경
- ROT(Running Object Table)를 통해 IPC(Inter-Process Communication)통신을 이루는 COM Server/Client. 본 채널을 가리켜 lightweight RPC라고 한다나?(Server와 Client 모두 동일 호스트에서 동작하기 때문에 RPC는 아니라고).
- COM Server는 USB 드라이브와 통신하며, COM Client는 IE browser에 내장되어 Server와 연결짓는 역할(따라서 COM client 역시 browser를 위한 COM Server 역할을 담당). Client의 메서드와 이벤트는 javascript를 통해 호출 및 수신한다.
- COM Server/Client 모두의 threading model은 STA(Single Thread Apartment).
- COM Server 쪽에는 UI가 있어 내장 IE Browser가 달려있음.
- COM Server 메서드 호출은 성공. 허나 COM Server에서 event firing시 Fire 위치에 따라 성공 또는 실패하는 황당한 상황이 발생. 실패 시 HRESULT 값 : 0x8001010d(An outgoing call cannot be made since the application is dispatching an input-synchronous call)
- 우연찮게 COM Server의 threading model을 MTA(Multi Thread Apartment)로 바꿨더니, 1의 문제가 사라짐. 하지만 내장 IE Browser window의 위치가 desktop window origin에 달라붙어 떨어지지 않는 상황이 발생(MoveWindow() 등의 API가 전혀 안먹음).
- 이벤트 메서드(Fire_XX()) 호출이 실패한 위치는 USB 드라이브 측에서 던진 message(드라이브 연결/끊김 등) handler 내에서였음. 본 handler는 message를 던진 측 routine과 동기적으로 동작하기에, 본 handler 내에서 (process 외부에서 동기적으로 동작할?) method를 호출할 수 없기에 발생함. 위 HRESULT 값을 통해 본 사항을 간접적으로 확인할 수 있겠다.
- 동기적으로 발생하는 calling chain을 끊어버린다. 즉, USB event handler 내에서 non-blocking 모드로 동작하는 PostMessage()를 던짐으로써 USB 드라이브에서 던진 message에 대해 비동기적으로 이벤트를 처리한다.
reference : http://discuss.develop.com/archives/wa.exe?A2=ind0303a&L=atl&P=3378
-
왜 MTA 기반에서는 정상적으로 동작했을까? STA
기반의 COM Server에서는 이벤트 발생 메서드인 Fire_XX()가 동기적으로 동작하나(blocking mode), MTA에서는 non-blocking
모드로 동작하기에 동기적 calling chain이 만들어지지 않으므로. 왜 이런식으로 동작하는지는 연구 대상.
COM threading model reference :
Understanding and Using COM Threading
INFO: Descriptions and Workings of OLE Threading Models - MTA 기반에서 IE Browser window의 위치가 제멋대로 노는 원인은 미결. IE Browser Control은 out-of-process COM이라는데, 요게 단서가 될지도 모른다는...
- message가 SendMessage(동기 모드)으로 던저졌는지, PostMessage(비동기 모드)로 던저졌는지 그걸 뭔 수로 아는가. 딱히 구분할 값을 던져주는 것도 아니고. 각 message에 대한 설명서를 일일이 확인해야 하는 상황. 나참, 어이가 없어서리.


댓글을 달아 주세요