1
0
Fork 0

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:
timoore 2009-05-19 22:14:35 +00:00 committed by Tim Moore
parent 0ce5f350ff
commit 8e1248e1e1
3 changed files with 61 additions and 8 deletions

View file

@ -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( \

View file

@ -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);

View file

@ -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}
};