64bit exceptions in WndProc silently fail
Asked Answered
M

5

7

The following code will give a hard fail when run under Windows 7 32bit:

void CTestView::OnDraw(CDC* /*pDC*/)
{
    *(int*)0 = 0; // Crash

    CTestDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: add draw code for native data here
}

However, if I try this on Windows 7 64bit, I just get this in the output window:

First-chance exception at 0x13929384 in Test.exe: 0xC0000005: Access violation writing location 0x00000000.
First-chance exception at 0x77c6ee42 in Test.exe: 0xC0150010: The activation context being deactivated is not active for the current thread of execution.

What is the reason for this? I know it's a hardware exception (http://msdn.microsoft.com/en-us/library/aa363082.aspx), but why the difference when ran under 32bit and 64bit? And what can I do to correctly handle these kind of errors? Because they should really be trapped and fixed, as opposed to what currently happens which is Windows just carries on pumping messages to the application and let's it run (so the user and the developers are completely unaware any problems have actually occurred).

Update: Our regular crash reporting software uses SetUnhandledExceptionFilter but that doesn't get called on x64 for hardware exceptions inside a WndProc. Does anyone have any information on this, or a workaround?

Update2: I've reported the issue at Microsoft Connect:
https://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

Missal answered 13/4, 2010 at 16:46 Comment(3)
I don't suppose simply compiling for 64-bit is an option?Intercalary
Compiling for x64 isn't really an option, our source code consists of approximately 1million lines of code, with a considerable amount of assembler too. Combine that with the added cost of running two separate builds through QA etc.Missal
See also the remarks section of WindowProc callback functionKaete
M
1

OK, I've received a reply from Microsoft:

Hello,

Thanks for the report. I've found out that this is a Windows issue, and there is a hot fix available. Please see http://support.microsoft.com/kb/976038 for a fix that you can install if you wish.

@Skute: note that the Program Compatibility Assistant will ask once if the program should be allowed to continue to execute, and after that it will always be allowed, so that may be the cause of the confusing behavior you are seeing.

Pat Brenner Visual C++ Libraries Development

So the workaround is either make sure the hotfix is installed, or wrap each WndProc in your application with a __try / __except block.

Missal answered 14/7, 2010 at 8:16 Comment(4)
Could you provide more information where do you use __try __except? Is it even possible to catch exception from WindowProc in catch block in C++ application. About hotfix I set DisableUserModeCallbackFilter to 1 in registry and best I get is FATAL_USER_CALLBACK_EXCEPTION, not my exception.Amourpropre
You use __try __except in your WNDPROC function, or if you're using MFC that would be the CWnd::OnMsg function (I think, that's off the top of my head, may be wrong).Missal
Is it possible to throw exception from WindowProc, not catch in WindowProc?Amourpropre
If you throw an exception and not catch it, it will crash... (or at least it should, but that's not what actually happens in x64, as Microsoft have a try / catch in their WindowProc, so your code will continue running).Missal
V
3

There's another exception being raised while the stack is being unwound for the Access Violation exception. Which is being swallowed, causing the AV to disappear. You'll need to find out what code is doing this. Debug + Exceptions, check the Thrown box for Win32 Exceptions. The debugger will stop on the first one, continue. Check out the call stack when it stop again. Add it to your question if you can't figure it out.

Vanitavanity answered 13/4, 2010 at 17:22 Comment(1)
The activation context exception only occurs when the AV exception is thrown.Missal
M
1

OK, I've received a reply from Microsoft:

Hello,

Thanks for the report. I've found out that this is a Windows issue, and there is a hot fix available. Please see http://support.microsoft.com/kb/976038 for a fix that you can install if you wish.

@Skute: note that the Program Compatibility Assistant will ask once if the program should be allowed to continue to execute, and after that it will always be allowed, so that may be the cause of the confusing behavior you are seeing.

Pat Brenner Visual C++ Libraries Development

So the workaround is either make sure the hotfix is installed, or wrap each WndProc in your application with a __try / __except block.

Missal answered 14/7, 2010 at 8:16 Comment(4)
Could you provide more information where do you use __try __except? Is it even possible to catch exception from WindowProc in catch block in C++ application. About hotfix I set DisableUserModeCallbackFilter to 1 in registry and best I get is FATAL_USER_CALLBACK_EXCEPTION, not my exception.Amourpropre
You use __try __except in your WNDPROC function, or if you're using MFC that would be the CWnd::OnMsg function (I think, that's off the top of my head, may be wrong).Missal
Is it possible to throw exception from WindowProc, not catch in WindowProc?Amourpropre
If you throw an exception and not catch it, it will crash... (or at least it should, but that's not what actually happens in x64, as Microsoft have a try / catch in their WindowProc, so your code will continue running).Missal
M
0

The only way we've managed to work around this problem is to put a __try / __except around each WndProc callback in the application. We then route the exception to our exception handler. Horrible, but looks like it's a problem with Windows itself. Still waiting on Microsoft to get back to us.

Missal answered 10/7, 2010 at 20:44 Comment(0)
E
0

I would venture a guess that the problem is actually related to how SEH works in x64. If your exception has to go back up through kernel-mode while the stack is unwinding, then what you're stuck with is by-design behavior: The case of the disappearing OnLoad exception. Windows is "handling" your exception for you; the hot-fix is a workaround to make specific x64 apps crash just like x86 does.

Electrodynamic answered 9/12, 2010 at 15:44 Comment(0)
C
0

I did some homework to find this: the exception is caught by windows. Here are stacks and disassembling:

stack and disassembling when wndproc get called

Circumfluous answered 26/6, 2013 at 6:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.