diff --git a/App/main.cpp b/App/main.cpp index 0b853e97d747d9983411c4cf357bd24553f36e1f..9bea2b0ac4ac08ed6cc9ba3679ea027fcc2d0bc7 100644 --- a/App/main.cpp +++ b/App/main.cpp @@ -28,6 +28,15 @@ #include <QMetaType> #include <QtGlobal> +auto guiFailedAssertion = [](std::string msg) { +#ifdef BA_DEBUG + std::cerr << "FATAL (catched in debug mode): " << msg << std::endl; + std::raise(11); // abort so that we can inspect the backtrace +#else + qFatal(msg.c_str()); +#endif +}; + int main(int argc, char* argv[]) { ApplicationOptions options(argc, argv); @@ -46,7 +55,7 @@ int main(int argc, char* argv[]) ApplicationSettings applicationSettings; qInstallMessageHandler(messageHandler); - failedAssertion = [](std::string msg) { qFatal(msg.c_str()); }; + failedAssertion = guiFailedAssertion; register1DDataLoaders(); diff --git a/Base/Util/Assert.cpp b/Base/Util/Assert.cpp index 57712bfdc847b0f8b59a63c781f0f4f41081b355..39ede6f9478faede379e3e8a51f5155c75d076cd 100644 --- a/Base/Util/Assert.cpp +++ b/Base/Util/Assert.cpp @@ -13,14 +13,7 @@ // ************************************************************************************************ #include "Base/Util/Assert.h" -#include <csignal> -#include <iostream> std::function<void(std::string)> failedAssertion = [](std::string msg) { -#ifdef BA_DEBUG - std::cerr << msg << std::endl; - std::raise(11); // abort so that we can inspect the backtrace -#else throw std::runtime_error(msg); -#endif }; diff --git a/Base/Util/Assert.h b/Base/Util/Assert.h index 7e8a61a4e75aca38a5ca82b69bf063d7837f99fc..1c4a66c3563507d605853a994033d8764050e2ee 100644 --- a/Base/Util/Assert.h +++ b/Base/Util/Assert.h @@ -20,23 +20,46 @@ #include "Wrap/WinDllMacros.h" #include <functional> -#include <sstream> -#include <stdexcept> #include <string> // Function called upon failed assert; set in Assert.cpp, overriden by GUI. extern BA_BASE_API_ std::function<void(std::string)> failedAssertion; -// ASSERT must be declared as a macro, not a function, in order for the error -// message to correctly report the source line where the assertion failed. +// ASSERT macro: terminate if condition is false. +// +// Implementation notes: +// - Must be declared as a macro, not a function, so that we can use preprocessor +// macros for informative error messages. +// - Must terminate with a throw statement to prevent compiler warning -Wreturn-type. +// - In the GUI, the function pointer failedAssertion will be reset to call qFatal, +// which then pops up a message window (as defined by qInstallMessageHandler). +// - No direct call to qFatal here, because we do not want core to depend on Qt, +// lest Python wheel becomes too difficult. + +#ifdef BA_DEBUG +#include <csignal> +#include <iostream> +#define ASSERT(condition) \ + if (!(condition)) { \ + std::cerr << "Assertion " << (#condition) << " failed in " << __FILE__ << ", line " \ + << __LINE__ << std::endl; \ + std::raise(SIGTERM); /* abort so that we can inspect the backtrace */ \ + throw std::runtime_error("Assertion failed ... and we should never get here"); \ + } + +#else + +#include <sstream> +#include <stdexcept> #define ASSERT(condition) \ if (!(condition)) { \ std::stringstream msg; \ msg << "Assertion " << (#condition) << " failed in " << __FILE__ << ", line " << __LINE__; \ failedAssertion(msg.str()); \ - /* The following throw is needed to prevent compiler warning -Wreturn-type */ \ throw std::runtime_error("Assertion failed ... and we should never get here"); \ } +#endif // BA_DEBUG + #endif // BORNAGAIN_BASE_UTIL_ASSERT_H