以下是简短的重现样本:
DWORD WINAPI _threadTest (LPVOID)
{
Sleep (2000);
CoInitialize(0);
CoCreateInstance(...); // <---- hangs here
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize (0);
CreateThread (0, 0, _threadTest, 0, 0, 0);
uint32_t size = 0;
fread (&size, 4, 1, stdin);
return 0;
}
因此。首先,问题仅在Windows XP下发生。
其次,这个控制台应用程序实际上是Firefox浏览器扩展的一部分。扩展使用stdin / stdout管道与它通信。
现在最有趣的事情。如果使用cmd.exe(例如)启动此EXE,则无法重现该问题。它仅在Firefox浏览器启动时才会重现。 即使我推出了EXE,我也不会重现这个问题,以防我评论网络电话并使用Sleep(10000)代替它。
目标COM组件处于单独的进程中。
所以,以及#34;挂起&#34; CoCreateInstance我们需要: 1. Windows XP 2. Firefox推出的流程 3.流程&#39;主线程被fread调用锁定。
会发生什么以及可以在这做什么?
来自我的真实应用程序的堆栈跟踪:
Worker Thread Win32 Thread sxs.dll!__ioinit Normal
ntdll.dll!_KiFastSystemCallRet@0()
ntdll.dll!_NtQueryVolumeInformationFile@20()
kernel32.dll!_GetFileType@4()
sxs.dll!__ioinit()
sxs.dll!__CRT_INIT@12()
sxs.dll!DllStartup_CrtInit(struct HINSTANCE__ *,unsigned long,void *)
sxs.dll!__SxsDllMain@12()
ntdll.dll!_LdrpCallInitRoutine@16()
ntdll.dll!_LdrpRunInitializeRoutines@4()
ntdll.dll!_LdrpLoadDll@24()
ntdll.dll!_LdrLoadDll@16()
kernel32.dll!_LoadLibraryExW@12()
kernel32.dll!_LoadLibraryW@4()
oleaut32.dll!OaLoadLibraryAW(char const *,unsigned short const *)
oleaut32.dll!GetRedirectionProcAddress(char const *,void * *)
oleaut32.dll!MapIIDToFusionCLSID(struct _GUID const &,struct _GUID *)
oleaut32.dll!ProxyStubCLSIDOfInterface(struct _GUID const &,struct _GUID *)
oleaut32.dll!CPSFactory::CreateProxy(struct IUnknown *,struct _GUID const &,struct IRpcProxyBuffer * *,void * *)
ole32.dll!CStdMarshal::CreateProxy(struct _GUID const &,struct IRpcProxyBuffer * *,void * *,int *)
ole32.dll!CStdMarshal::MakeCliIPIDEntry(struct _GUID const &,struct tagSTDOBJREF *,class OXIDEntry *,struct tagIPIDEntry * *)
ole32.dll!CStdMarshal::UnmarshalIPID(struct _GUID const &,struct tagSTDOBJREF *,class OXIDEntry *,void * *)
ole32.dll!CStdMarshal::Finish_RemQIAndUnmarshal1(struct tagSQIResult *,struct tagQICONTEXT *)
ole32.dll!CStdMarshal::Finish_QueryRemoteInterfaces(struct tagSQIResult *,struct tagQICONTEXT *)
ole32.dll!CStdMarshal::QueryRemoteInterfaces(unsigned short,struct _GUID *,struct tagSQIResult *)
ole32.dll!CStdIdentity::CInternalUnk::QueryMultipleInterfaces(unsigned long,struct tagMULTI_QI *)
ole32.dll!CStdIdentity::CInternalUnk::QueryInterface(struct _GUID const &,void * *)
FmBrowserHelper.exe!_com_ptr_t<_com_IIID<IWGUrlReceiver,&_GUID_454a4044_16ec_4d64_9069_c5b8832b7b55> >::CreateInstance(const _GUID & rclsid, IUnknown * pOuter, unsigned long dwClsContext) Line 592
Microsoft Visual C ++的fread实现在零句柄(stdin)上调用_lock_fh,然后在_read_nolock调用中锁定线程(尝试从stdin读取)。我想问题就在这里...当主线程从fread退出时 - CoCreateInstance返回。
答案 0 :(得分:0)
很酷的工作,我认为你需要这样做:
CoInitializeEx(null, COINIT_APARTMENTTHREADED);
正如在此处所做的那样:https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Examples/Using_COM_from_js-ctypes