diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 65c3d828caf..4e7c9732ee7 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "AddressManager.h" #include "Application.h" @@ -49,6 +50,16 @@ extern "C" { } #endif +#ifdef Q_OS_UNIX +#include +static int fpe_counter = 0; +static void fpe_handler(int signum) { + // This currently exists just to have something to pass to the SIGFPE handler, + // and to serve as a point where to put a breakpoint. + ++fpe_counter; +} +#endif + int main(int argc, const char* argv[]) { #ifdef Q_OS_MAC auto format = getDefaultOpenGLSurfaceFormat(); @@ -372,6 +383,11 @@ int main(int argc, const char* argv[]) { "Which graphics API to target. Supports gl45, gl41, and gles32. Final API may vary based on system support.", "string" ); + QCommandLineOption floatExceptionsOption( + "floatExcept", + "Trigger an exception for the chosen floating point conditions, comma separated: divbyzero, inexact, invalid, overflow, underflow, all. This is a debugging option.", + "string" + ); parser.addOption(urlOption); parser.addOption(protocolVersionOption); @@ -419,6 +435,8 @@ int main(int argc, const char* argv[]) { parser.addOption(xrNoHandTrackingOption); parser.addOption(xrNoPalmPoseOption); parser.addOption(graphicsAPIOption); + parser.addOption(floatExceptionsOption); + QString applicationPath; // A temporary application instance is needed to get the location of the running executable @@ -585,6 +603,34 @@ int main(int argc, const char* argv[]) { return 0; } + if (parser.isSet(floatExceptionsOption)) { + QStringList opts = parser.value(floatExceptionsOption).split(","); + int flags = 0; + + for (const auto &opt : opts) { + if (opt == "divbyzero") { + flags |= FE_DIVBYZERO; + } else if (opt == "inexact") { + flags |= FE_INEXACT; + } else if (opt == "invalid") { + flags |= FE_INVALID; + } else if (opt == "overflow") { + flags |= FE_OVERFLOW; + } else if (opt == "underflow") { + flags |= FE_UNDERFLOW; + } else if (opt == "all") { + flags = FE_ALL_EXCEPT; + } else { + qCritical() << "Invalid value for --floatExcept option: " << opt; + return 2; + } + } + + feenableexcept(flags); +#ifdef Q_OS_UNIX + signal(SIGFPE, fpe_handler); +#endif + } static const QString APPLICATION_CONFIG_FILENAME = "config.json"; QDir applicationDir(applicationPath); diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index aabe6f36ba5..d788064d5f4 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "Logging.h" #include "impl/SharedObject.h" @@ -457,7 +458,26 @@ void OffscreenSurface::finishQmlLoad(QQmlComponent* qmlComponent, // Call this callback after rootitem is set, otherwise VrMenu wont work callback(qmlContext, newItem); } + + // There's a huge amount of divides by zero that happen with floating point exceptions + // enabled. It makes useful debugging impossible, so we're selectively disabling them + // here. Unfortunately fedisableexcept isn't standard and not available on Windows. + // + // On Windows, this might be unusable. Perhaps some sort of modification to QML + // might be possible. +#ifndef Q_OS_WIN + fexcept_t fflags; + + fegetexceptflag(&fflags, FE_ALL_EXCEPT); + fedisableexcept(FE_ALL_EXCEPT); +#endif + qmlComponent->completeCreate(); + +#ifndef Q_OS_WIN + fesetexceptflag(&fflags, FE_ALL_EXCEPT); +#endif + qmlComponent->deleteLater(); }