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

Re: wait instruction resulting in BSOD by Tim

Tim
Fri Jul 27 23:44:50 CDT 2007

"John Keenan" <john.removeme.keenan@optimapowerware.com> wrote:
>...
>__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?

Are you saying that you did this in a user-mode application and it
generated a blue screen? That's not supposed to be possible.

Or are you saying you did this in a kernel driver?
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Re: wait instruction resulting in BSOD by John

John
Sat Jul 28 10:55:48 CDT 2007

"Tim Roberts" <timr@probo.com> wrote:
> > 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?
>
> Are you saying that you did this in a user-mode application and it
> generated a blue screen? That's not supposed to be possible.
>
> Or are you saying you did this in a kernel driver?

This occurs in a user-mode application (MFC) running in the Visual Studio
debugger and generates a blue screen. I also did not think this was
possible.

John



Re: wait instruction resulting in BSOD by Alexander

Alexander
Sat Jul 28 13:19:29 CDT 2007

Can you post a reproducible case here, trimmed to minimum?

"John Keenan" <john.removeme.keenan@optimapowerware.com> wrote in message
news:8GJqi.53486$5j1.4176@newssvr21.news.prodigy.net...
> "Tim Roberts" <timr@probo.com> wrote:
>> > 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?
>>
>> Are you saying that you did this in a user-mode application and it
>> generated a blue screen? That's not supposed to be possible.
>>
>> Or are you saying you did this in a kernel driver?
>
> This occurs in a user-mode application (MFC) running in the Visual Studio
> debugger and generates a blue screen. I also did not think this was
> possible.
>
> John
>
>



Re: wait instruction resulting in BSOD by John

John
Sat Jul 28 17:08:00 CDT 2007

"Alexander Grigoriev" <alegr@earthlink.net> wrote:

> Can you post a reproducible case here, trimmed to minimum?

I am working on it.

John



This code forces me to turn-off my PC. by Jeff_Relf

Jeff_Relf
Tue Aug 21 00:42:26 CDT 2007

You ( Tim Roberts ) told John Keenan:
â?? Are you saying that you did this in a user-mode application and it
generated a blue screen? That's not supposed to be possible. â??.

About 2 weeks ago, my code blue-screened my WinXP box,
other times it spontaneously rebooted.

I even crashed the VC++ 8.0 compiler ( yet again ),
the report was sent to MicroSoft.

I was really tired at the time so I didn't try to reproduce it.
This code forces me to turn-off my PC:

#pragma warning( disable: 4100 4127 4189 4430 4508 4706 )
#define _WIN32_WINNT 0x0501
#define UNICODE
#include <Windows.H>

#define Quote_It( It ) #It
#define DD_Path( __X ) Quote_It( \
C:\\Program Files\\Microsoft DirectX SDK (December 2005)\\__X )
#include DD_Path( Include\\DDraw.H )
#pragma comment( lib , DD_Path( Lib\\x86\\DDraw.LIB ) )
#pragma comment( lib , DD_Path( Lib\\x86\\DXguid.LIB ) )
#include DD_Path( Include\\Dxerr8.H )
#pragma comment( lib , DD_Path( Lib\\x86\\Dxerr8.LIB ) )

#define CW CreateWindow
#define _SurT LPDIRECTDRAWSURFACE7
#define SetPtr SelectObject
#define Loop( N ) int J = - 1 , LLL = N ; while ( ++ J < LLL )

typedef unsigned int uint; typedef wchar_t * LnP ;

LPDIRECTDRAW _Direct_Draw; LPDIRECTDRAW7 Direct_Draw;
DDSURFACEDESC2 Z = { sizeof Z, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH };
HWND Win ;

long __stdcall WinProc ( HWND Wnd, uint _WM, uint C, long C2 ) {
return 1 ; }

#define Okay ( \
rv >= 0 || rv == DDERR_WASSTILLDRAWING || rv == DDERR_SURFACELOST )
int Chk( int rv ) { if ( Okay ) return rv ;
LnP Err = LnP( DXGetErrorString8( rv ) );
return rv ; }

int W = 32000, H = 20, rv, CacheW, CacheH, X ; HDC DC ; HFONT Fnt ;
BlueScreen() { _SurT Oops ; Z.dwWidth = W , Z.dwHeight = H ;
Chk( Direct_Draw->CreateSurface( & Z, & Oops, 0 ) );

if ( Oops && ! ( rv = Oops->GetDC( & DC ) ) ) {
SetPtr( DC, Fnt );
Loop( W / CacheW + 3 ) TextOut( DC, X += CacheW, 0, L"X", 1 ); }

if ( Oops && ! rv ) BlueScreen(); }

__stdcall WinMain( HINSTANCE PID, HINSTANCE, char*, int ) {

DirectDrawCreate( 0, & _Direct_Draw, 0 );
_Direct_Draw->QueryInterface( IID_IDirectDraw7, (VOID**) & Direct_Draw );
if ( ! _Direct_Draw ) return ;

WNDCLASS Class = { 0, WinProc , 0,0, PID, 0, 0, 0, 0, L"WinProc" };
RegisterClass( & Class );
Win = CW(L"WinProc", 0, 0, 0, 0, 1, 1, 0, 0, PID, 0 );

Direct_Draw->SetCooperativeLevel( Win, DDSCL_NORMAL );
Z.ddsCaps.dwCaps = DDSCAPS_TEXTURE ; // DDSCAPS_VIDEOMEMORY

Fnt = CreateFont( CacheH = 64, 0,0,0,0,0,0,0,0,0,0,0,0, L"MS Mincho");
CacheW = CacheH * 128 / 256 ;
BlueScreen(); }


This BlueScreened my PC, but usually it just kills XP's GDI. by Jeff_Relf

Jeff_Relf
Wed Aug 22 23:02:46 CDT 2007

// This BlueScreened my PC, but usually it just kills XP's GDI.

#define Quote_It( It ) #It
#define DD_Path( __X ) Quote_It( \
C:\\Program Files\\Microsoft DirectX SDK (December 2005)\\__X )
#include DD_Path( Include\\DDraw.H )
#pragma comment( lib , DD_Path( Lib\\x86\\DDraw.LIB ) )
#pragma comment( lib , DD_Path( Lib\\x86\\DXguid.LIB ) )

int __stdcall WinMain( HINSTANCE, HINSTANCE, char*, int ) {

LPDIRECTDRAW DD; LPDIRECTDRAW7 DirectDraw;
DirectDrawCreate( 0, & DD, 0 );
DD->QueryInterface( IID_IDirectDraw7, (VOID**) & DirectDraw );

DirectDraw->SetCooperativeLevel( 0, DDSCL_NORMAL );
DDSURFACEDESC2 Z = { sizeof Z, DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH };
// DDSCAPS_VIDEOMEMORY wouldn't freeze/BlueScreen Win XP's GDI
Z.ddsCaps.dwCaps = DDSCAPS_TEXTURE ;

int CacheH = 64, CacheW = CacheH / 2 ;
HFONT Fnt = CreateFont( CacheH, 0,0,0,0,0,0,0,0,0,0,0,0,0 );
int W = 32000, H = 2, X = - CacheW ;
LPDIRECTDRAWSURFACE7 Oops ; Z.dwWidth = W, Z.dwHeight = H ;

DirectDraw->CreateSurface( & Z, & Oops, 0 );
HDC DC ; Oops->GetDC( & DC ); SelectObject( DC, Fnt );

#define Loop( N ) int J = - 1 , LLL = N ; while ( ++ J < LLL )
Loop( W / CacheW ) TextOut( DC, X += CacheW, 0, "X", 1 );
return 1 ; }


=?UTF-8?Q?=E2=80=9C?= _fpreset(); _controlfp( controlfp, 0 ); =?UTF-8?Q?=E2=80=9D?= BlueScreens because... by Jeff_Relf

Jeff_Relf
Wed Aug 22 23:26:10 CDT 2007

I think â?? _fpreset(); _controlfp( controlfp, 0 ); â??
BlueScreens because the implicit call to â?? wait â??
causes other processes to run with invalid FPU settings.


Re: " _fpreset(); _controlfp( controlfp, 0 ); " BlueScreens because... by Ben

Ben
Tue Aug 28 15:12:25 CDT 2007


"Jeff?Relf" <Jeff_Relf@Yahoo.COM> wrote in message
news:Jeff_Relf_2007_Aug_22__9_26_PK@Cotse.NET...
>I think " _fpreset(); _controlfp( controlfp, 0 ); "
> BlueScreens because the implicit call to " wait "
> causes other processes to run with invalid FPU settings.

The FP control word should be saved in the state buffer associated with each
kernel thread during a context switch.



=?UTF-8?Q?=E2=80=A1?= Re: " _fpreset(); _controlfp( controlfp, 0 ); " BlueScreens because... by Jeff_Relf

Jeff_Relf
Tue Aug 28 16:12:07 CDT 2007

You ( Mr. Voigt ) told me:
â?? The FP control word should be saved in
the state buffer associated with each kernel thread
during a context switch. â??.

That's good to know. Mr. Keenan's B.S.o.D.
must have something to do with stepping on XP's shared resourses.

My â?? news:Jeff_Relf_2007_Aug_22__9_2_Pt@Cotse.NET â?? code
will BlueScreen my WinXP box, but ususally it just kills the G.D.I.


Re: " _fpreset(); _controlfp( controlfp, 0 ); " BlueScreens because... by Ben

Ben
Wed Aug 29 09:26:00 CDT 2007


"Jeff?Relf" <Jeff_Relf@Yahoo.COM> wrote in message
news:Jeff_Relf_2007_Aug_28__2_12_PG@Cotse.NET...
> You ( Mr. Voigt ) told me:
> " The FP control word should be saved in
> the state buffer associated with each kernel thread
> during a context switch. ".
>
> That's good to know. Mr. Keenan's B.S.o.D.
> must have something to do with stepping on XP's shared resourses.

That's the point: the FP control word isn't shared between processes,
because it is saved and restored by the kernel task switcher.

However, SEH clearly messes with the FPU in order to raise FPU exceptions,
and most likely there's some really evil interaction going on there.

A kernel debugger would be needed to find out where execution goes when the
thread running _control87 hits that wait (since presumably a task switch
occurs, and the task switcher needs to save the FP control word, which is
the same thing _control87 is trying to accomplish in the first place).



Why does anyone use exceptions ? by Jeff_Relf

Jeff_Relf
Wed Aug 29 17:29:33 CDT 2007

Why does anyone use exceptions ?
I wanted to --> turn off <-- interger exceptions,
so I came to M.P.VC.Language.

The response I got was: â?? f u c k i n' handle it, you d w e e b. â??.
All I see is people who positively --> love <-- exceptions... boring !

From searching other groups, the only â?? solution â?? I saw was:

#define _WIN32_WINNT 0x0501
#include <Windows.H>
#pragma warning( disable: 4007 4189 4244 4430 4508 )

#define TheDIV ( * ( int * ) ep->ContextRecord->Eip & 0x0000F000 )
#define ForGlobals ( 3 * ( 0x3000 == TheDIV ) )
long _stdcall filter( PEXCEPTION_POINTERS ep ) {
ep->ContextRecord->Eip += 3 + ForGlobals ;
ep->ContextRecord->Eax = 0x7FFFFFFF ;
return EXCEPTION_CONTINUE_EXECUTION ; }

int Z ;
func() { Z /= Z ; Z -- ; }

__stdcall WinMain( HINSTANCE, HINSTANCE, char*, int ) {
AddVectoredExceptionHandler( 1, & filter );
func();
} // â?? Z â?? now contains 0x7FFFFFFE .