这个Windows API调用WaitForSingleObject有什么问题?

What's wrong with this Windows API call WaitForSingleObject?

本文关键字:什么 问题 WaitForSingleObject Windows API 调用 这个      更新时间:2023-10-16

该进程在Windows 7中崩溃不稳定。我在WinDbg中使用!analyze -v命令进行异常分析。它告诉以下信息。异常实际上是由IrsSim!IrsNet_BlockOutput调用WaitForSingleObject函数引发的。WinDbg 的异常分析告诉我这是INVALID_POINTER_READ错误。

对于调用代码,pChannel->hMutex不是NULL。我已经转储了它并检查了它的价值。

IRSNETRET IrsNet_BlockOutput( IRSNET    *pChannel)
{
// Check channel
    IRSNET_CHECK_CHANNEL(pChannel);
// Wait for synchronization mutex
    switch(WaitForSingleObject(pChannel->hMutex, INFINITE))
    {
...
}

<<<<<======

====

FAULTING_IP:艾尔斯西姆!渠道::发送Irs消息+285 [s:\som5\ics\scsv\isv\test.u\irssim\irsiftransport.cpp @ 539] 00520ed5 8B06 MOV EAX,DWORD PTR [ESI]

EXCEPTION_RECORD: fffffffff -- (.exr 0xffffffffffffffff( 异常地址: 77db4639 (新台币!RtlDeactivateActivationContextUnsafeFast+0x00000058(
异常代码: c0150010 异常标志: 00000001 数字参数: 3 参数[0]: 00000000 参数[1]: 07befc58 参数[2]: 00000000

DEFAULT_BUCKET_ID:INVALID_POINTER_READ

PROCESS_NAME:IrsSim.exe

ERROR_CODE:(NTSTATUS( 0xc0150010 - 激活上下文 "已停用"对于当前执行线程不处于活动状态。

EXCEPTION_CODE:(NTSTATUS( 0xc0150010 - 激活上下文 "已停用"对于当前执行线程不处于活动状态。

EXCEPTION_PARAMETER1: 00000000

EXCEPTION_PARAMETER2:07befc58

EXCEPTION_PARAMETER3: 00000000

STACK_TEXT: 07d2fce0 00520ed5 irssim!渠道::发送Irs消息+0x285 07d2fd1c 00521072 伊尔西姆!CChannelArray::SendIrsMessage+0x132 07d2fd50 0052208a 伊尔西姆!CNetLibInterface::SendIrsMessage+0xba 07d2fd78 005C01B6 伊西姆!CSendActivity::Execute+0x76 07d2fdac 005e0b3f 嘘!SimulationThreadState::ExecuteOneActivity+0x11f 07d2fdf8 005CC937 呵呵!CSimulationSubThreadState::ExecuteState+0x267 07d2fe8c 005CCF02 呵呵!ThreadFctSubSimulation+0xf2 07d2fec4 73b1e3ee MFC90U!_AfxThreadEntry+0xf2 07D2FF4C 739F3433 msvcr90!_endthreadex+0x44 07d2ff84 739f34c7 msvcr90!_endthreadex+0xd8 07d2ff90 767d339a 内核32!BaseThreadInitThunk+0xe 07d2ff9c 77d69ed2 NTDLL!__RtlUserThreadStart+0x70 07D2FFDC 77D69EA5 NTDLL!_RtlUserThreadStart+0x1b

====

==================================

之后,我使用 !teb 命令尝试获取更多堆栈信息。

0:011> k L=07beec2c 100 ChildEBP RetAddr 07bef54c 76be0bdd 新人!NtWaitForMultipleObjects+0x15 07bef5e8 767d1a2c 内核基础!等待多个对象Ex+0x100 07bef630 767d4208 内核32!WaitForMultipleObjectsExImplementation+0xe0 07bef64c 767f80a4 内核32!等待多个对象+0x18 07bef6b8 767f7f63 内核32!WerpReportFaultInternal+0x186 07bef6cc 767f7858 内核32!WerpReportFault+0x70 07bef6dc 767f77d7 内核32!BasepReportFault+0x20 07bef768 77da21d7 内核32!未处理异常过滤器+0x1af 07bef770 77da20b4 NTDLL!__RtlUserThreadStart+0x62 07BEF784 77DA1F59 NTDLL!_EH4_CallFilterFunc+0x12 07BEF7AC 77D76AB9 NTDLL!_except_handler4+0x8e 07BEF7D0 77D76A8B 新人!ExecuteHandler2+0x26 07bef7f4 77d76a2d ntdll!执行处理程序+0x24 07bef880 77d40143 新台币!RtlDispatchException+0x127 07bef880 77db4639 新人!KiUserExceptionDispatcher+0xf 07befc34 76be0ad7 新人!RtlDeactivateActivationContextUnsafeFast+0x58 07befc38 76be0abc 内核基础!WaitForSingleObjectEx+0xde 07befc98 767d1194 内核基础!WaitForSingleObjectEx+0xc3 07befcb0 767d1148 内核32!WaitForSingleObjectExImplementation+0x75

07befcc4 005e3b6e 内核32!等待单一对象+0x12

07befcd4 00520d3b IrsSim!IrsNet_BlockOutput+0x1e

07befd14 00521072 艾尔斯西姆!渠道::发送Irs消息+0xeb 07befd48 0052208a IrsSim!CChannelArray::SendIrsMessage+0x132 07befd70 005c01b6 伊尔斯西姆!CNetLibInterface::SendIrsMessage+0xba 07befda4 005e0b3f 伊尔斯西姆!CSendActivity::Execute+0x76 07befdf0 005cc937 伊尔斯西姆!模拟线程状态::执行一个活动+0x11f 07befe84 005ccf02 艾尔斯西姆!CSimulationSubThreadState::ExecuteState+0x267 07befebc 73b1e3ee IrsSim!ThreadFctSubSimulation+0xf2 07beff44 739f3433 MFC90U!_AfxThreadEntry+0xf2 07BEFF7C 739F34C7 msvcr90!_endthreadex+0x44 07beff88 767d339a msvcr90!_endthreadex+0xd8 07beff94 77d69ed2 内核32!BaseThreadInitThunk+0xe 07beffd4 77d69ea5 NTDLL!__RtlUserThreadStart+0x70 07beffec 00000000 NTDLL!_RtlUserThreadStart+0x1b

======================================================

>>>>>>=

======================================================================

看起来很像 MFC 应用程序中遇到的0xC015000f异常("正在停用的激活上下文不是最近激活的上下文。

在我遇到此异常的所有情况下,异常都不是主要问题。这是早期异常的副作用,通常是访问冲突,其中堆栈未正确展开。在异常处理中,某处缺少使用宏(如AFX_MANAGE_STATE宏(的调用帧。结果是,下次操作激活上下文时,例如通过另一个导致调用 AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2 之类的例程,系统会检测到 cookie 不匹配并引发异常。

在您的情况下,您可能会在一段代码中导致异常(很可能是 AV(,然后由上下文异常表现出来。若要捕获根本原因,请在启用首次机会异常处理的情况下运行调试器。这样,可能使用 try/catch(...( 的人在呼叫帧的其他地方被捕获的 AV 将被暴露出来。由于您似乎在线程化,因此您可能只是在内存访问上存在争用条件,从而导致主要异常(如果确实是正在发生的事情(。

我在上一篇文章中看到:"事实上,这个问题来自于将程序从64位Win XP移植到64位Win7。因此,编译器从 VC6 切换到 VC9。">

这不是 MFC 中的错误。MFC 6 不包括在 Visual Studio 2005 中添加的激活上下文切换代码(基于 cookie(。因此,您不会遇到此异常。我们也认为较新的 MFC 有问题,但在我们遇到的每种情况下,都是我们的代码导致了问题。原始问题被代码流掩盖,这些代码流以 try/catch(通常...(开头,最终调用使用其中一个 MFC 管理状态宏的代码,然后调用更多代码,最终会发生 AV。由于捕获位于堆栈的上游,并且根据损坏情况,并非所有帧都正确展开,因此缺少 MFC 宏的背面(某些析构函数无法弹出其上下文(。更糟糕的是(对于调试(,最终的上下文崩溃可能发生在代码中的任何位置(我们在 CWnd 的基本窗口消息处理路由方法中遇到过很多(。我们最终为用户创建了另一个运行工具,该工具将自身作为调试器附加到我们的(发布目标(可执行文件,该可执行文件捕获了第一次机会异常并创建了一个 dmp 文件,以便我们可以找到异常发生的初始点,因为上下文异常的转储几乎从来没有用过,因为问题的原始来源早已过去执行。

调用以这种方式失败的唯一方法是

pChannel->hMutex

无效。要么pChannel本身是无效的,要么hMutex.很可能是前者。

您应该

检查句柄是否无效,而不仅仅是NULL

if (myHandle != INVALID_HANDLE_VALUE)
{
    // do something
}

通常,如果出现错误,创建句柄函数将返回此值。

看起来像上下文

停用中的问题(基于windbg转储的想法(。请参阅 http://blogs.msdn.com/b/junfeng/archive/2006/03/19/sxs-activation-context-activate-and-deactivate.aspx 文章。