rework error handling mechanism

This commit is contained in:
wmayer
2018-10-24 19:38:43 +02:00
parent ea4fb69e4e
commit a53027342e
5 changed files with 92 additions and 45 deletions

View File

@@ -171,7 +171,8 @@ MESSAGE(STATUS "cmake: ${CMAKE_VERSION}")
# ==============================================================================
# == Win32 is default behaviour use the LibPack copied in Source tree ==========
if(MSVC)
OPTION(FREECAD_RELEASE_PDB "Create PDB file for Release version." ON)
OPTION(FREECAD_RELEASE_PDB "Create PDB files for Release version." ON)
OPTION(FREECAD_RELEASE_SEH "Enable Structured Exception Handling for Release version." ON)
OPTION(FREECAD_LIBPACK_USE "Use the LibPack to Build FreeCAD (only Win32 so far)." ON)
OPTION(FREECAD_LIBPACK_USEPYSIDE "Use PySide in LibPack rather to PyQt and Swig." ON)
set(FREECAD_LIBPACK_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Directory of the FreeCAD LibPack")
@@ -1098,8 +1099,8 @@ ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8)
IF(MSVC)
# set default compiler settings
SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /EHa /Zm128")
SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFC_DEBUG /Zm128")
SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zm150")
SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFC_DEBUG /Zm150")
# set default libs
SET (CMAKE_C_STANDARD_LIBRARIES "kernel32.lib user32.lib gdi32.lib winspool.lib SHFolder.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib winmm.lib comsupp.lib Ws2_32.lib dbghelp.lib ")
set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}")
@@ -1111,6 +1112,9 @@ IF(MSVC)
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
set (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG")
ENDIF(FREECAD_RELEASE_PDB)
IF(FREECAD_RELEASE_SEH)
SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /EHa")
ENDIF(FREECAD_RELEASE_SEH)
# Mark 32 bit executables large address aware so they can use > 2GB address space
# NOTE: This setting only has an effect on machines with at least 3GB of RAM, although it sets the linker option it doesn't set the linker switch 'Enable Large Addresses'

View File

@@ -138,6 +138,10 @@ using namespace boost::program_options;
#include <App/CMakeScript.h>
#ifdef _MSC_VER // New handler for Microsoft Visual C++ compiler
# if !defined(_DEBUG) && defined(HAVE_SEH)
# define FC_SE_TRANSLATOR
# endif
# include <new.h>
# include <eh.h> // VC exception handling
#else // Ansi C/C++ new handler
@@ -1226,7 +1230,7 @@ void segmentation_fault_handler(int sig)
}
}
void my_terminate_handler()
void unhandled_exception_handler()
{
std::cerr << "Terminating..." << std::endl;
}
@@ -1242,23 +1246,28 @@ void unexpection_error_handler()
#endif
}
#ifdef _MSC_VER // Microsoft compiler
void my_trans_func( unsigned int code, EXCEPTION_POINTERS* pExp )
#if defined(FC_SE_TRANSLATOR) // Microsoft compiler
void my_se_translator_filter(unsigned int code, EXCEPTION_POINTERS* pExp)
{
Q_UNUSED(pExp)
switch (code)
{
case EXCEPTION_ACCESS_VIOLATION:
throw Base::AccessViolation();
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
throw Base::DivisionByZeroError("Division by zero!");
break;
}
//switch (code)
//{
// case FLT_DIVIDE_BY_ZERO :
// //throw CMyFunkyDivideByZeroException(code, pExp);
// throw Base::DivisionByZeroError("Division by zero!");
// break;
//}
// general C++ SEH exception for things we don't need to handle separately....
throw Base::RuntimeError("my_trans_func()");
std::stringstream str;
str << "SEH exception of type: " << code;
// general C++ SEH exception for things we don't need to handle separately....
throw Base::RuntimeError(str.str());
}
#endif
void Application::init(int argc, char ** argv)
{
try {
@@ -1274,13 +1283,14 @@ void Application::init(int argc, char ** argv)
#if defined (_MSC_VER) // Microsoft compiler
std::signal(SIGSEGV,segmentation_fault_handler);
std::signal(SIGABRT,segmentation_fault_handler);
std::set_terminate(my_terminate_handler);
std::set_terminate(unhandled_exception_handler);
std::set_unexpected(unexpection_error_handler);
// _set_se_translator(my_trans_func);
#elif defined(FC_OS_LINUX)
std::signal(SIGSEGV,segmentation_fault_handler);
#endif
#if defined(FC_SE_TRANSLATOR)
_set_se_translator(my_se_translator_filter);
#endif
initTypes();
#if (BOOST_VERSION < 104600) || (BOOST_FILESYSTEM_VERSION == 2)

View File

@@ -3,6 +3,10 @@ if(WIN32)
add_definitions(-DBOOST_DYN_LINK)
endif(WIN32)
if(FREECAD_RELEASE_SEH)
add_definitions(-DHAVE_SEH)
endif(FREECAD_RELEASE_SEH)
# This causes some problems with the resource files to be found, especially with the StartPage
IF(RESOURCEDIR)
add_definitions(-DRESOURCEDIR="${RESOURCEDIR}")

View File

@@ -131,29 +131,59 @@ short FeatureTest::mustExecute(void) const
DocumentObjectExecReturn *FeatureTest::execute(void)
{
/*
doc=App.newDocument()
obj=doc.addObject("App::FeatureTest")
int *i=0,j;
float f;
void *s;
obj.ExceptionType=0 # good
doc.recompute()
// Code analyzers may complain about some errors. This can be ignored
// because this is done on purpose to test the error handling mechanism
switch(ExceptionType.getValue())
{
case 0: break;
case 1: throw "Test Exception";
case 2: throw Base::RuntimeError("FeatureTestException::execute(): Testexception");
case 3: *i=0;printf("%i",*i);break; // seg-vault
case 4: j=0; printf("%i",1/j); break; // int division by zero
case 5: f=0.0; printf("%f",1/f); break; // float division by zero
case 6: s = malloc(3600000000ul); free(s); break; // out-of-memory
}
ExecCount.setValue(ExecCount.getValue() + 1);
obj.ExceptionType=1 # unknown exception
doc.recompute()
ExecResult.setValue("Exec");
obj.ExceptionType=2 # Runtime error
doc.recompute()
return DocumentObject::StdReturn;
obj.ExceptionType=3 # segfault
doc.recompute()
obj.ExceptionType=4 # segfault
doc.recompute()
obj.ExceptionType=5 # int division by zero
doc.recompute()
obj.ExceptionType=6 # float division by zero
doc.recompute()
*/
int *i=0,j;
float f;
void *s;
std::string t;
// Code analyzers may complain about some errors. This can be ignored
// because this is done on purpose to test the error handling mechanism
switch(ExceptionType.getValue())
{
case 0: break;
case 1: throw "Test Exception";
case 2: throw Base::RuntimeError("FeatureTestException::execute(): Testexception");
#if 0 // only allow these error types on purpose
case 3: *i=0;printf("%i",*i);break; // seg-fault
case 4: t = nullptr; break; // seg-fault
case 5: j=0; printf("%i",1/j); break; // int division by zero
case 6: f=0.0; printf("%f",1/f); break; // float division by zero
case 7: s = malloc(3600000000ul); free(s); break; // out-of-memory
#else
default: (void)i; (void)j; (void)f; (void)s; (void)t; break;
#endif
}
ExecCount.setValue(ExecCount.getValue() + 1);
ExecResult.setValue("Exec");
return DocumentObject::StdReturn;
}
@@ -162,14 +192,13 @@ PROPERTY_SOURCE(App::FeatureTestException, App::FeatureTest)
FeatureTestException::FeatureTestException()
{
ADD_PROPERTY(ExceptionType,(Base::Exception::getClassTypeId().getKey()) );
ADD_PROPERTY(ExceptionType,(Base::Exception::getClassTypeId().getKey()) );
}
DocumentObjectExecReturn *FeatureTestException::execute(void)
{
//ExceptionType;
//ExceptionType;
throw Base::RuntimeError("FeatureTestException::execute(): Testexception ;-)");
throw Base::RuntimeError("FeatureTestException::execute(): Testexception ;-)");
return 0;
return 0;
}

View File

@@ -237,7 +237,7 @@ PyMOD_INIT_FUNC(Part)
// Python's cmath module.
// For Linux use segmentation_fault_handler in Application.cpp
#if !defined(_DEBUG) && !defined(FC_OS_LINUX)
OSD::SetSignal(Standard_False);
//OSD::SetSignal(Standard_False);
#endif
PyObject* partModule = Part::initModule();