Add --enable-fpe option to cause a trap on floating point exceptions
Only on Linux for now; traps on divide by zero and "invalid", which includes generating a NaN and overflowing an integer conversion.
This commit is contained in:
parent
0ce5f350ff
commit
8e1248e1e1
3 changed files with 61 additions and 8 deletions
|
@ -625,6 +625,13 @@ fi
|
|||
LIBS=$save_LIBS
|
||||
CPPFLAGS=$save_CPPFLAGS
|
||||
|
||||
AC_MSG_CHECKING([for feenableexcept])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _GNU_SOURCE
|
||||
#include <fenv.h>]], [[feenableexcept(FE_DIVBYZERO)]])],
|
||||
[AC_DEFINE([HAVE_FEENABLEEXCEPT], 1, [define if system has fenableexcept])],
|
||||
AC_MSG_RESULT([yes]),
|
||||
AC_MSG_RESULT([no]))
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS( \
|
||||
|
|
|
@ -25,7 +25,12 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__i386__)
|
||||
#if defined(HAVE_FEENABLEEXCEPT)
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <fenv.h>
|
||||
#elif defined(__linux__) && defined(__i386__)
|
||||
# include <fpu_control.h>
|
||||
#endif
|
||||
|
||||
|
@ -38,6 +43,7 @@
|
|||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
@ -55,9 +61,28 @@ bool free_hostname = false;
|
|||
// foreward declaration.
|
||||
void fgExitCleanup();
|
||||
|
||||
#if defined(__linux__) && defined(__i386__)
|
||||
static bool fpeAbort = false;
|
||||
static void handleFPE(int);
|
||||
static void initFPE();
|
||||
|
||||
static void handleFPE (int);
|
||||
#if defined(HAVE_FEENABLEEXCEPT)
|
||||
static void
|
||||
initFPE ()
|
||||
{
|
||||
if (fpeAbort) {
|
||||
int except = fegetexcept();
|
||||
feenableexcept(except | FE_DIVBYZERO | FE_INVALID);
|
||||
} else {
|
||||
signal(SIGFPE, handleFPE);
|
||||
}
|
||||
}
|
||||
|
||||
static void handleFPE(int)
|
||||
{
|
||||
feclearexcept(FE_ALL_EXCEPT);
|
||||
signal(SIGFPE, handleFPE);
|
||||
}
|
||||
#elif defined(__linux__) && defined(__i386__)
|
||||
|
||||
static void
|
||||
initFPE ()
|
||||
|
@ -80,6 +105,14 @@ handleFPE (int num)
|
|||
initFPE();
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Floating point interrupt (SIGFPE)");
|
||||
}
|
||||
#else
|
||||
static void handleFPE(int)
|
||||
{
|
||||
}
|
||||
|
||||
static void initFPE()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -134,12 +167,18 @@ int main ( int argc, char **argv ) {
|
|||
#endif
|
||||
_bootstrap_OSInit = 0;
|
||||
|
||||
#if defined(__linux__) && defined(__i386__)
|
||||
// Enable floating-point exceptions for Linux/x86
|
||||
initFPE();
|
||||
#elif defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__)
|
||||
// Ignore floating-point exceptions on FreeBSD
|
||||
signal(SIGFPE, SIG_IGN);
|
||||
signal(SIGFPE, SIG_IGN);
|
||||
#else
|
||||
// Maybe Enable floating-point exceptions on Linux
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (!strcmp("--enable-fpe", argv[i])) {
|
||||
fpeAbort = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
initFPE();
|
||||
#endif
|
||||
#if !defined( _MSC_VER ) && !defined( __MINGW32__ )
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
|
|
@ -1209,6 +1209,12 @@ fgOptVersion( const char *arg )
|
|||
return FG_OPTIONS_EXIT;
|
||||
}
|
||||
|
||||
static int
|
||||
fgOptFpe(const char* arg)
|
||||
{
|
||||
// Actually handled in bootstrap.cxx
|
||||
}
|
||||
|
||||
static map<string,size_t> fgOptionMap;
|
||||
|
||||
/*
|
||||
|
@ -1417,6 +1423,7 @@ struct OptionDesc {
|
|||
{"ai-scenario", true, OPTION_FUNC, "", false, "", fgOptScenario },
|
||||
{"parking-id", true, OPTION_FUNC, "", false, "", fgOptParking },
|
||||
{"version", false, OPTION_FUNC, "", false, "", fgOptVersion },
|
||||
{"enable-fpe", false, OPTION_FUNC, "", false, "", fgOptFpe},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue