]> git.mxchange.org Git - flightgear.git/commitdiff
Add --enable-fpe option to cause a trap on floating point exceptions
authortimoore <timoore>
Tue, 19 May 2009 22:14:35 +0000 (22:14 +0000)
committerTim Moore <timoore@redhat.com>
Tue, 2 Jun 2009 22:18:54 +0000 (00:18 +0200)
Only on Linux for now; traps on divide by zero and "invalid", which includes
generating a NaN and overflowing an integer conversion.

configure.ac
src/Main/bootstrap.cxx
src/Main/options.cxx

index 7ea6728bf5be291f5dc66ce4023dcbe83e78e5c7..3ea1d4f501d180400e3c1639993fb46afa048cee 100644 (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( \
index 734f998c0978fde2e8954ea7bacdad2a1d92225c..aa9c314a2e3f44c71c812f2477ae6712f0ad5098 100644 (file)
 #  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);
index 3c09df562d6ebff428e80c21b11bcd8ba2fd93f3..fbe82388c422b61acdef23864a2c7baed5a44727 100644 (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}
 };