My application follows the architecture described in MSDN article titled
"Handling Exceptions, Part 17" by Robert Schmidt dated March 16, 2000 to
catch structured exceptions and throw C++ exceptions derived from
std::exception in their place. This has been in service for 6 years and
works well except for EXCEPTION_FLT_INVALID_OPERATION. I recently decided to
dig a little deeper into the problems with this one particular exception.
The code snippet of interest is:
case EXCEPTION_FLT_INVALID_OPERATION:{
// _clearfp() did not work here. _fpreset() does work here but blows
// away the floating-point processor settings. Hence need to first get
// the floating-point processor settings and then restore them after
invoking
// _fpreset. This allows the floating-point processor settings
// to be maintained for each thread.
unsigned int controlfp = _controlfp( 0, 0 ); // Get the current
floating-point processor settings.
_fpreset(); // Initialize the floating-point processor.
_controlfp( controlfp, _MCW_DN | _MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC );
// Set the floating-point processor settings to what they were.
throw ::PTI_system_exception_flt_invalid_operation( *info_ );
}
break;
I am able to force this exception to by attempting operations with NaNs with
the floating-point mask settings that I use. But the call to _controlfp
results in a BSOD. _controlfp internally invokes _control87 (no surprise)
and _control87 disassembly is:
__control87:
1021A0B0 push ebp
1021A0B1 mov ebp,esp
1021A0B3 sub esp,10h
1021A0B6 push ebx
1021A0B7 push esi
1021A0B8 push edi
1021A0B9 wait
1021A0BA fnstcw word ptr [ebp-10h]
1021A0BD mov ax,word ptr [ebp-10h]
1021A0C1 push eax
1021A0C2 call __fpreset+60h (1021a180)
<snip>
The BSOD occurs at the wait instruction.
My questions are:
1) Why is there a wait instruction in _control87?
2) Why does a wait instruction in the context of a structured exception
cause a BSOD?
John