| /** | |
| * 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 |