【发布时间】:2015-08-30 14:19:03
【问题描述】:
我的 C++ 应用程序会不时地使用基于此页面的 MSDN 示例的代码遍历多个应用程序的 MSAA 树:https://msdn.microsoft.com/en-us/library/windows/desktop/dd317975(v=vs.85).aspx
它运行良好,直到几个月前我开始注意到有时线程在 AccessibleChildren 调用时冻结。
这是我所知道的:
- 这种情况不会经常发生
- 在遍历不同应用程序的树时会发生这种情况。
- 它肯定没有连接到当前节点的子节点数量,因为我已经调试了底部调用
childCount等于 1 的小型转储。 - 它发生在不同的 PC 上。
- 处于这种位置的线程永远不会唤醒。一旦发生冻结,线程将保持此状态,直到应用重新启动。
- 有时线程在这样的迭代过程中简单地死掉了,在这种情况下,我无法捕捉到它的堆栈跟踪。然后应用程序的其余部分继续运行,但转储显示给定线程不再工作,尽管它的任务基本上是无限循环和睡眠。我认为它与冻结有关。以某种方式。
我的问题是:有人能指出这种冻结的原因以及如何防止它们吗?如果没有,有没有办法将递归移动到另一个线程,可以安全地从另一个线程“超时”?
这是此类事件的示例堆栈跟踪,其中顶部是最嵌套的调用。我从这里删除了递归以缩短阅读时间。
--> ntdll.dll!_NtWaitForMultipleObjects@20() Unknown
ntdll.dll!_NtWaitForMultipleObjects@20() Unknown
KERNELBASE.dll!_WaitForMultipleObjectsEx@20() Unknown
kernel32.dll!_WaitForMultipleObjectsExImplementation@20() Unknown
user32.dll!_RealMsgWaitForMultipleObjectsEx@20() Unknown
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 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 C++
ole32.dll!CAptRpcChnl::SendReceive(tagRPCOLEMESSAGE * pMsg, unsigned long * pulStatus) Line 583 C++
ole32.dll!CCtxComChnl::SendReceive(tagRPCOLEMESSAGE * pMessage, unsigned long * pulStatus) Line 659 C++
ole32.dll!NdrExtpProxySendReceive(void * pThis, _MIDL_STUB_MESSAGE * pStubMsg) Line 1932 C++
rpcrt4.dll!@NdrpProxySendReceive@4() Unknown
rpcrt4.dll!_NdrClientCall2() Unknown
ole32.dll!ObjectStublessClient(void * ParamAddress, long Method) Line 474 C++
ole32.dll!_ObjectStubless@0() Line 154 Unknown
ole32.dll!CStdMarshal::Begin_RemQIAndUnmarshal1(unsigned short cIIDs, _GUID * pIIDs, tagQICONTEXT * pQIC) Line 4551 C++
ole32.dll!CStdMarshal::Begin_QueryRemoteInterfaces(unsigned short cIIDs, _GUID * pIIDs, tagQICONTEXT * pQIC) C++
ole32.dll!CStdMarshal::QueryRemoteInterfaces(unsigned short cIIDs, _GUID * pIIDs, tagSQIResult * pQIRes) Line 4284 C++
ole32.dll!CStdIdentity::CInternalUnk::QueryMultipleInterfaces(unsigned long cMQIs, tagMULTI_QI * pMQIs) Line 596 C++
ole32.dll!CStdIdentity::CInternalUnk::QueryInterface(const _GUID & riid, void * * ppv) Line 352 C++
ole32.dll!IUnknown_QueryInterface_Proxy(IUnknown * This, const _GUID & riid, void * * ppv) Line 1723 C++
ole32.dll!CoUnmarshalInterface(IStream * pStm, const _GUID & riid, void * * ppv) Line 996 C++
oleacc.dll!UnmarshalInterface(unsigned char const *,unsigned long,struct _GUID const &,void * *) Unknown
oleacc.dll!FreeUpSlot(struct OutstandingObjectEntry *) Unknown
oleacc.dll!_ObjectFromLresult@16() Unknown
oleacc.dll!NativeIAccessibleFromWindow(struct HWND__ *,unsigned long,struct _GUID const &,void * *) Unknown
oleacc.dll!_ORIGINAL_AccessibleObjectFromWindow@16() Unknown
oleacc.dll!_AccessibleObjectFromWindow@16() Unknown
oleacc.dll!GetWindowObject(struct HWND__ *,struct tagVARIANT *) Unknown
oleacc.dll!CClient::Next(unsigned long,struct tagVARIANT *,unsigned long *) Unknown
oleacc.dll!AccWrap_Base::Next(unsigned long,struct tagVARIANT *,unsigned long *) Unknown
oleacc.dll!_AccessibleChildren@20() Unknown
//my recursion ends here
【问题讨论】:
-
客户端和服务器是否在同一个用户下运行?此外,MSAA 非常不受欢迎。你试过 UIA:msdn.microsoft.com/en-us/library/windows/desktop/ee684009.aspx
-
我正在使用 UIA,但由于我的一些客户端 PC 不是最新的 XP,我也不得不继续支持 MSAA。我不确定用户,但问题并不足以让我假设,例如当我的应用程序作为普通用户时,有人总是以管理员身份运行 Internet Explorer。我在这里可以猜到的最接近的一件事是有问题的程序(如 IE)想要运行下载的文件,并且以某种方式用户访问控制导致了我的问题,但我对 UAC 机制还不够熟悉,无法知道这是否属实。
标签: c++ com iaccessible