मैं आउट-ऑफ-प्रो COM सर्वर (COM सिंगलटन "इंजन" का उपयोग कर रहा हूं DECLARE_CLASSFACTORY_SINGLETON का उपयोग करके कार्यान्वित), यह एसटीए (CComSingleThreadModel, _ATL_APARTMENT_THREADED) में काम करता है।आउट-ऑफ-प्रो COM सर्वर
COM सर्वर ग्राहकों:
- ActiveScript (JScript), (मैं AddNamedItem का उपयोग कर इंजन संदर्भ पारित)।
- दो स्वतंत्र आईई बीएचओ।
बीएचओ समय-समय पर इंजन :: dispatchEvent, इंजन को सक्रिय स्क्रिप्ट के जावास्क्रिप्ट कार्यों को कॉल करता है। यह आर्किटेक्चर पूरी तरह से काम करता है जब तक कि मैं एक साथ दो बीएचओ चालू नहीं करता।
यदि मैं दो बीएचओ चालू करता हूं, तो अटक जाता है जब मैं सक्रिय स्क्रिप्ट का कार्य करता हूं (IDISpatch/Invoke का उपयोग करके)। मैं कोई अतिरिक्त धागा नहीं बनाता हूं।
कुछ नोट:
- मैं BHO से ActiveScript को पुनः प्राप्त वस्तु पारित नहीं करते हैं (या इंजन में बनाए गए एक ही वस्तु के साथ बदलने) सब कुछ ठीक काम करता है।
- अटक तब होती है जब जेस्क्रिप्ट कचरा कलेक्टर बीएचओ (IUnknown_Release_Proxy में कॉलस्टैक) से पुनर्प्राप्त ऑब्जेक्ट को रिलीज़ करने का प्रयास करता है।
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
क्रियान्वयन विवरण:
// 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);
}
}
}
हाँ, आवश्यक थ्रेड संदर्भ स्विच के कारण डेडलॉक जब जावास्क्रिप्ट आपकी ऑब्जेक्ट को रिलीज़ करने का प्रयास करता है। आपको उस थ्रेड को देखने की ज़रूरत है जिसने मूल रूप से ऑब्जेक्ट बनाया है और देखें कि यह उत्तरदायी क्यों नहीं है। यदि यह अवरुद्ध है तो आपको इस मार्शल कॉल को पूरा करने के लिए MsgWaitForMultipleObjectsEx की आवश्यकता है। –
बीएचओ थ्रेड प्रतिक्रिया नहीं दे रहा है क्योंकि यह प्रेषण के लिए इंतजार कर रहा है परिणाम (oleaut32.dll! _IDispatch_Invoke_Proxy, user32.dll! _RealMsgWaitForMultipleObjectsEx कॉलस्टैक में)। – KAdot
मैंने कार्यान्वयन विवरण जोड़ा है। – KAdot