c# - Application hanging during CoCreateInstance of .NET-based COM object -
i have c++ dll creating instance of com object that's implemented in .net. under many circumstances works fine, under circumstances, hangs application, , see stuck following call stack (this part underneath level of dll's code):
ntdll.dll!_ntalpcsendwaitreceiveport@32() rpcrt4.dll!lrpc_cassociation::alpcsendwaitreceiveport(unsigned long,struct _port_message *,struct _alpc_message_attributes *,struct _port_message *,unsigned long *,struct _alpc_message_attributes *,union _large_integer *) rpcrt4.dll!lrpc_base_ccall::dosendreceive(void) rpcrt4.dll!lrpc_base_ccall::sendreceive(struct _rpc_message *) rpcrt4.dll!_i_rpcsendreceive@4() rpcrt4.dll!_ndrsendreceive@8() rpcrt4.dll!@ndrpsendreceive@4() rpcrt4.dll!_ndrclientcall2() combase.dll!serverallocateoxidandoids(void * hserver, void * phprocess, unsigned __int64 * poxidserver, unsigned long coids, unsigned __int64 * aoid, unsigned long * pcoidsallocated, const tagoxid_info * poxidinfo, tagdualstringarray * pdsastringbindings, tagdualstringarray * pdsasecuritybindings, unsigned __int64 * pdworbindingsid, tagdualstringarray * * ppdsaorbindings) line 246 combase.dll!crpcresolver::serverregisteroxid(const tagoxid_info & oxidinfo, unsigned __int64 * poxid, unsigned long * pcoidstoallocate, unsigned __int64 * arnewoidlist) line 1020 combase.dll!oxidentry::registeroxidandoids(unsigned long * pcoids, unsigned __int64 * poids) line 1631 combase.dll!oxidentry::allocoids(unsigned long * pcoidsalloc, unsigned __int64 * poidsalloc, unsigned long coidsreturn, unsigned __int64 * poidsreturn) combase.dll!ccomapartment::calltheresolver() line 856 combase.dll!ccomapartment::initremoting() line 1166 combase.dll!ccomapartment::startserver() line 1386 combase.dll!initchannelifnecessary() line 1393 combase.dll!classicstathreadwaitforhandles(unsigned long dwflags, unsigned long dwtimeout, unsigned long chandles, void * * phandles, unsigned long * pdwindex) line 34 combase.dll!cowaitformultiplehandles(unsigned long dwflags, unsigned long dwtimeout, unsigned long chandles, void * * phandles, unsigned long * lpdwindex) mscorwks.dll!nt5waitroutine(int,unsigned long,int,void * *,int) mscorwks.dll!msgwaithelper(int,void * *,int,unsigned long,int) mscorwks.dll!thread::doappropriateaptstatewait(int,void * *,int,unsigned long,enum waitmode) mscorwks.dll!thread::doappropriatewaitworker(int,void * *,int,unsigned long,enum waitmode) mscorwks.dll!thread::doappropriatewait(int,void * *,int,unsigned long,enum waitmode,struct pendingsync *) mscorwks.dll!clrevent::waitex(unsigned long,enum waitmode,struct pendingsync *) mscorwks.dll!clrevent::wait(unsigned long,int,struct pendingsync *) mscorwks.dll!cexecutionengine::waitforevent(void *,unsigned long,int) mscorwks.dll!clrwaitevent(void *,unsigned long,int) mscorwks.dll!fusionsink::wait(void) mscorwks.dll!assemblysink::wait(void) mscorwks.dll!fusionbind::remoteload(struct iapplicationcontext *,class fusionsink *,struct iassemblyname *,struct iassembly *,unsigned short const *,struct iassembly * *,struct ihostassembly * *,struct iassembly * *,int) mscorwks.dll!fusionbind::loadassembly(struct iapplicationcontext *,class fusionsink *,struct iassembly * *,struct ihostassembly * *,struct iassembly * *,int) mscorwks.dll!assemblyspec::findassemblyfile(class appdomain *,int,struct iassembly * *,struct ihostassembly * *,struct iassembly * *,struct ifusionbindlog * *,enum stackcrawlmark *) mscorwks.dll!appdomain::bindassemblyspec(class assemblyspec *,int,int,enum stackcrawlmark *) mscorwks.dll!assemblyspec::loaddomainassembly(enum fileloadlevel,class object * *,class object * *,int,int,int,enum stackcrawlmark *) mscorwks.dll!assemblyspec::loadassembly(enum fileloadlevel,class object * *,class object * *,int,int,int,enum stackcrawlmark *) mscorwks.dll!appdomain::loadassemblyhelper(unsigned short const *,unsigned short const *) mscorwks.dll!appdomain::loadcomclass(struct _guid,int,int *) mscorwks.dll!gettypeforclsid(struct _guid const &,int *) mscorwks.dll!eedllgetclassobject(struct _guid const &,struct _guid const &,void * *) mscorwks.dll!_internaldllgetclassobject@12() mscorwks.dll!_dllgetclassobjectinternal@12() mscoreei.dll!_dllgetclassobject@12() combase.dll!cclasscache::cdllpathentry::getclassobject(const _guid & pclsid, const _guid & piid, void * * ppv) line 2691 combase.dll!cclasscache::cdllpathentry::dllgetclassobject(const _guid & rclsid, const _guid & riid, iunknown * * ppunk, int fmakevalid) line 3892 combase.dll!cclasscache::cdllfnptrmoniker::bindtoobjectnoswitch(const _guid & riid, void * * ppvresult) line 4406 combase.dll!cclasscache::getclassobject(const activation_properties & ap) line 5816 combase.dll!cservercontextactivator::createinstance(iunknown * punkouter, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties) line 999 combase.dll!activationpropertiesin::delegatecreateinstance(iunknown * punkouter, iactivationpropertiesout * * ppactpropsout) line 1854 combase.dll!capartmentactivator::createinstance(iunknown * punkouter, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties) line 2323 combase.dll!cprocessactivator::ccicallback(unsigned long dwcontext, iunknown * punkouter, activationpropertiesin * pactin, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties) combase.dll!cprocessactivator::attemptactivation(activationpropertiesin * pactin, iunknown * punkouter, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties, hresult (unsigned long, iunknown *, activationpropertiesin *, iactivationpropertiesin *, iactivationpropertiesout * *) * pfnctxactcallback, unsigned long dwcontext) line 1673 combase.dll!cprocessactivator::activatebycontext(activationpropertiesin * pactin, iunknown * punkouter, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties, hresult (unsigned long, iunknown *, activationpropertiesin *, iactivationpropertiesin *, iactivationpropertiesout * *) * pfnctxactcallback) line 1539 combase.dll!cprocessactivator::createinstance(iunknown * punkouter, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties) line 1417 combase.dll!activationpropertiesin::delegatecreateinstance(iunknown * punkouter, iactivationpropertiesout * * ppactpropsout) line 1854 combase.dll!cclientcontextactivator::createinstance(iunknown * punkouter, iactivationpropertiesin * pinactproperties, iactivationpropertiesout * * ppoutactproperties) line 713 combase.dll!activationpropertiesin::delegatecreateinstance(iunknown * punkouter, iactivationpropertiesout * * ppactpropsout) combase.dll!icocreateinstanceex(const _guid & originalclsid, iunknown * punkouter, unsigned long dwclsctx, _coserverinfo * pserverinfo, unsigned long dwcount, unsigned long dwactvflags, tagmulti_qi * presults, activationpropertiesin * pactin) line 1645 combase.dll!ccomactivator::docreateinstance(const _guid & clsid, iunknown * punkouter, unsigned long dwclsctx, _coserverinfo * pserverinfo, unsigned long dwcount, tagmulti_qi * presults, activationpropertiesin * pactin) line 376 combase.dll!cocreateinstance(const _guid & rclsid, iunknown * punkouter, unsigned long dwcontext, const _guid & riid, void * * ppv) line 120 the circumstances under hanging occurs when following conditions met:
- the application running on clean windows 2012 r2 system have run install tries install minimal set of components application run.
- the application not creating , initializing instance of
microsoft_interopformtools.interoptoolboxbefore creating unrelated com object. - the application installed in reg-free manner rather using old installer has more overhead , registers com dlls in registry , .net dlls in gac, , possibly includes files minimal installer neglected.
if change first condition , run on local windows 7 development machine instead of clean windows 2012 server, problem doesn't occur. if change second condition code initializing interopformtools before creating com object, problem doesn't occur. if change third condition product installed using old comprehensive installer, problem doesn't occur.
how track down source of problem and/or fix it?
with assistance of microsoft support , debugdiag have determined cause of problem seems related loader lock. loader lock documented in detail @ https://msdn.microsoft.com/en-us/library/ms173266(v=vs.120).aspx basically, there restrictions apply code runs within scope of dllmain or dynamic initialization of static un-managed code objects instances require dynamic initialization on loading dll (because they're in global scope). 1 way around tell c++ compiler code should compiled clr support it's not handling initialization in dllmain, rather function doesn't retain loader lock.
in our code had global declaration:
cfscoculturewrapper culturewrapper; which had constructor called cocreateinstance on managed com object, in turn had reference microsoft.interoptoolbox. applying /clr switch 1 source file allowed dll loaded without hanging.
it's not clear why behavior changed in different deployments, but, article linked states, hang not occur, these can difficult problems debug. illustrate, our simple test case 4 levels deep loading dlls before encountered problem - exe loads (loadlibrary) unmanaged dll loads (cocreateinstance) managed dll loads microsoft dll. decided level of complexity involved in these sorts of problems enough understood , did not pursue further understanding why problem occurred in deployments.
simple answer, don't create global instances of objects load managed code during constructor unmanaged code. use lazy initialization or switch code file use /clr switch or use means of preventing execution of managed code during dllmain-time initialization. work-around discovered switching managed code use .net 4.5 instead of 2.0.
Comments
Post a Comment