Tôi đang sử dụng máy chủ COM out-of-proc (COM singleton "Engine" được triển khai bằng DECLARE_CLASSFACTORY_SINGLETON), nó hoạt động trong STA (CComSingleThreadModel, _ATL_APARTMENT_THREADED).Máy chủ COM out-of-proc bị kẹt
máy chủ COM khách hàng:
- ActiveScript (JScript), (tôi vượt qua tham khảo Engine sử dụng AddNamedItem).
- Hai BHO IE độc lập.
BHOs gọi định kỳ Engine :: dispatchEvent, Các cuộc gọi cơ động Các chức năng JavaScript của ActiveScript. Kiến trúc này hoạt động hoàn hảo cho đến khi tôi bật hai BHO cùng một lúc.
Nếu tôi bật hai BHO, bị kẹt xảy ra khi tôi gọi chức năng của ActiveScript (sử dụng IDispatch/Invoke). Tôi không tạo bất kỳ chủ đề bổ sung nào.
Một số lưu ý:
- Nếu tôi không vượt qua đối tượng lấy từ BHO để ActiveScript (hoặc thay thế nó với cùng một đối tượng được tạo ra trong Engine) tất cả mọi thứ hoạt động tốt.
- Bị kẹt chỉ xảy ra khi bộ thu gom rác JScript cố gắng giải phóng đối tượng được truy xuất từ BHO (IUnknown_Release_Proxy trong callstack).
callstack:
> [email protected]() + 0x15 bytes
[email protected]() + 0x15 bytes
[email protected]() + 0x100 bytes
[email protected]() + 0x8e bytes
[email protected]() + 0xe2 bytes
ole32.dll!CCliModalLoop::BlockFn(void * * ahEvent, unsigned long cEvents, unsigned long * lpdwSignaled) Line 1222 C++
ole32.dll!ModalLoop(CMessageCall * pcall) Line 211 C++
ole32.dll!ThreadSendReceive(CMessageCall * pCall) Line 4979 C++
ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall(CMessageCall * * ppCall) Line 4454 + 0x6 bytes C++
ole32.dll!CRpcChannelBuffer::SendReceive2(tagRPCOLEMESSAGE * pMessage, unsigned long * pstatus) Line 4076 C++
ole32.dll!CCliModalLoop::SendReceive(tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus, IInternalChannelBuffer * pChnl) Line 899 + 0x17 bytes C++
ole32.dll!CAptRpcChnl::SendReceive(tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus) Line 583 + 0xd bytes C++
ole32.dll!CCtxComChnl::SendReceive(tagRPCOLEMESSAGE * pMessage, unsigned long * pulStatus) Line 734 + 0xa bytes C++
ole32.dll!NdrExtpProxySendReceive(void * pThis, _MIDL_STUB_MESSAGE * pStubMsg) Line 1932 C++
[email protected]@4() + 0xe bytes
rpcrt4.dll!_NdrClientCall2() + 0x144 bytes
ole32.dll!ObjectStublessClient(void * ParamAddress, long Method) Line 474 + 0x8 bytes C++
[email protected]() Line 154 Asm
ole32.dll!RemoteReleaseRifRefHelper(IRemUnknown * pRemUnk, int fReleaseRemUnkProxy, int fProcessingPostedMessage, OXIDEntry * pOXIDEntry, unsigned short cRifRef, tagREMINTERFACEREF * pRifRef, IUnknown * pAsyncRelease) Line 6770 + 0xc bytes C++
ole32.dll!RemoteReleaseRifRef(CStdMarshal * pMarshal, OXIDEntry * pOXIDEntry, unsigned short cRifRef, tagREMINTERFACEREF * pRifRef) Line 6694 C++
ole32.dll!CStdMarshal::DisconnectCliIPIDs() Line 3964 C++
ole32.dll!CStdMarshal::Disconnect(unsigned long dwType) Line 3273 C++
ole32.dll!CStdIdentity::~CStdIdentity() Line 312 C++
ole32.dll!CStdIdentity::`scalar deleting destructor'() + 0xd bytes C++
ole32.dll!CStdIdentity::CInternalUnk::Release() Line 767 C++
ole32.dll!IUnknown_Release_Proxy(IUnknown * This) Line 1773 C++
[email protected]() + 0xac9 bytes
jscript.dll!VAR::Clear() + 0x50 bytes
jscript.dll!GcAlloc::ReclaimGarbage() + 0xa2 bytes
jscript.dll!GcContext::Reclaim() + 0x8e bytes
jscript.dll!GcContext::CollectCore() - 0x72f bytes
jscript.dll!GcContext::Collect() + 0x34 bytes
jscript.dll!CScriptRuntime::Run() - 0x864f bytes
jscript.dll!ScrFncObj::CallWithFrameOnStack() + 0xf3 bytes
jscript.dll!ScrFncObj::Call() + 0x84 bytes
jscript.dll!NameTbl::InvokeInternal() + 0x113 bytes
jscript.dll!VAR::InvokeByDispID() + 0x73 bytes
jscript.dll!CScriptRuntime::Run() + 0x1d89 bytes
jscript.dll!ScrFncObj::CallWithFrameOnStack() + 0xf3 bytes
jscript.dll!ScrFncObj::Call() + 0x84 bytes
jscript.dll!NameTbl::InvokeInternal() + 0x113 bytes
jscript.dll!VAR::InvokeByDispID() + 0x73 bytes
jscript.dll!CScriptRuntime::Run() + 0x1d89 bytes
jscript.dll!ScrFncObj::CallWithFrameOnStack() + 0xf3 bytes
jscript.dll!ScrFncObj::Call() + 0x84 bytes
jscript.dll!NameTbl::InvokeInternal() + 0x12c6 bytes
jscript.dll!VAR::InvokeByDispID() + 0x73 bytes
jscript.dll!NameTbl::GetVal() + 0x3b bytes
chi tiết thực hiện:
// Engine (out of process COM singleton)
class ATL_NO_VTABLE CEngine :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CEngine, &CLSID_Engine>,
public IDispatchImpl<IEngine, &IID_IEngine, &LIBID_EngineLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
DECLARE_CLASSFACTORY_SINGLETON(CEngine)
STDMETHOD(dispatchEvent)(BSTR name, IDispatch* pEvent, VARIANT_BOOL* pbSuccess)
{
// pEvent is CPropertyStore instance
ActiveScriptDispatch.Invoke1(L"FuncName", pEvent, &varResult);
}
}
// BHO
class CPropertyStore :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CPropertyStore, &CLSID_NULL>,
public IDispatch
{
BEGIN_COM_MAP(CPropertyStore)
COM_INTERFACE_ENTRY(IUnknown)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
BOOL SetProperty(CString strName, VARIANT *value)
{
// Store value in CAtlArray
}
// IDispatch impl
STDMETHOD(GetTypeInfoCount)(UINT *pctinfo);
STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult,EXCEPINFO *pExcepInfo, UINT *puArgErr);
}
class ATL_NO_VTABLE CBHO :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CBHO, &CLSID_BHO>,
public IObjectWithSiteImpl<CBHO>,
public IDispatchImpl<IBHO, &IID_IBHO, &LIBID_Lib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispEventImpl<1, CBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 0>
{
void onEvent(...)
{
if(m_pEngine == NULL && SUCCEEDED(m_pEngine.CoCreateInstance(CLSID_Engine)))
{
CComObject<CPropertyStore> *pEvent = NULL;
HRESULT hRes = CComObject<CPropertyStore>::CreateInstance(&pEvent);
CComVariant varEvent(pEvent);
CComVariant varName(L"EventName");
CComVariant varResult;
m_pEngine.Invoke2(L"dispatchEvent", &varName, &varEvent, &varResult);
}
}
}
Có, bế tắc do công tắc ngữ cảnh chủ đề bắt buộc khi Javascript cố gắng giải phóng đối tượng của bạn. Bạn cần phải xem xét các chủ đề mà ban đầu tạo ra các đối tượng và xem lý do tại sao nó không được đáp ứng. Nếu nó bị chặn thì bạn cần MsgWaitForMultipleObjectsEx để cho phép cuộc gọi này được hoàn thành. –
Chủ đề BHO không phản hồi vì nó đang chờ kết quả dispatchEvent (oleaut32.dll! _IDispatch_Invoke_Proxy, user32.dll! _RealMsgWaitForMultipleObjectsEx trong callstack). – KAdot
Tôi đã thêm chi tiết triển khai. – KAdot