blob: 310f23f7e68eed37f3bfd377fad122f3f218dbad [file]
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#if defined(__i386__)
#include <signal.h>
#include <float.h>
#include <excpt.h>
#include <windows.h>
int __cdecl __msvcrt_XcptFilter(unsigned long _ExceptionNum, struct _EXCEPTION_POINTERS *_ExceptionPtr);
int __cdecl _XcptFilter(unsigned long _ExceptionNum, struct _EXCEPTION_POINTERS *_ExceptionPtr)
{
/* Function _XcptFilter() in pre-msvcr100 libraries do not handle STATUS_FLOAT_MULTIPLE_FAULTS and STATUS_FLOAT_MULTIPLE_TRAPS SEH exceptions.
* These two SEH exceptions are thrown by Windows system for 32-bit x86 processes when SSE floating point exception occurs.
* So fix the pre-msvcr100 behavior and correctly calls SIGFPE signal handler for these exceptions.
* x87 floating point exceptions and also 64-bit x86 processes are correctly handled by msvcr* libraries. */
if (_ExceptionNum == STATUS_FLOAT_MULTIPLE_FAULTS || _ExceptionNum == STATUS_FLOAT_MULTIPLE_TRAPS)
{
__p_sig_fn_t handler = signal(SIGFPE, SIG_GET);
/* Function signal() in pre-msvcr80 libraries do not support SIG_GET, it sets the signal handler to SIG_GET.
* Detect this behavior and restore the retrieved signal handler back to the correct one. */
if (signal(SIGFPE, SIG_GET) == SIG_GET)
signal(SIGFPE, handler);
if (handler == SIG_DFL)
return EXCEPTION_CONTINUE_SEARCH;
else if (handler == SIG_IGN)
return EXCEPTION_CONTINUE_EXECUTION;
else
{
void *old_pxcptinfoptrs = _pxcptinfoptrs;
int old_fpecode = _fpecode;
_pxcptinfoptrs = _ExceptionPtr;
if (_ExceptionNum == STATUS_FLOAT_MULTIPLE_FAULTS)
_fpecode = _FPE_MULTIPLE_FAULTS;
else
_fpecode = _FPE_MULTIPLE_TRAPS;
signal(SIGFPE, SIG_DFL);
((void(__cdecl*)(int,int))(void(*)(void))handler)(SIGFPE, _fpecode);
_fpecode = old_fpecode;
_pxcptinfoptrs = old_pxcptinfoptrs;
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return __msvcrt_XcptFilter(_ExceptionNum, _ExceptionPtr);
}
int __cdecl (*__MINGW_IMP_SYMBOL(_XcptFilter))(unsigned long, struct _EXCEPTION_POINTERS *) = _XcptFilter;
#endif