diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index ead0439ef..bbca3a8b9 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -132,6 +132,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) else if (std::strcmp(argv[i], "--debug-fp") == 0) _settings->debugFalsePositive = true; + // (Experimental) exception handling inside cppcheck client + else if (std::strcmp(argv[i], "--exception-handling") == 0) + _settings->exceptionHandling = true; + // Inconclusive checking (still in testing phase) else if (std::strcmp(argv[i], "--inconclusive") == 0) _settings->inconclusive = true; diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 4b97ca9c2..91ecb78a0 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -32,6 +32,21 @@ #include #include +#if defined(__GNUC__) +#define USE_UNIX_SIGNAL_HANDLING +#include +#endif + +#ifdef USE_UNIX_SIGNAL_HANDLING +#include +#include +#endif + +#ifdef _MSC_VER +#include +#include +#endif + CppCheckExecutor::CppCheckExecutor() : _settings(0), time1(0), errorlist(false) { @@ -156,6 +171,83 @@ int CppCheckExecutor::check(int argc, const char* const argv[]) return EXIT_FAILURE; } + if (cppCheck.settings().exceptionHandling) { + return check_wrapper(cppCheck, argc, argv); + } else { + return check_internal(cppCheck, argc, argv); + } +} + +#if defined(USE_UNIX_SIGNAL_HANDLING) +extern "C" void MySignalHandler(int signo, siginfo_t *info, void *context); + +/* (declare this list here, so it may be used in signal handlers in addition to main()) + * A list of signals available in ISO C + * Check out http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html + * For now we only want to detect abnormal behaviour for a few selected signals: + */ +static const int listofsignals[] = { + /* don't care: SIGABRT, */ + SIGFPE, + SIGILL, + SIGINT, + SIGSEGV, + /* don't care: SIGTERM */ +}; + +static void print_stacktrace(FILE* f) +{ +#if defined(__GNUC__) + void *array[50]= {0}; + size_t size = backtrace(array, int(sizeof(array)/sizeof(array[0]))); + char **strings = backtrace_symbols(array, (int)size); + fprintf(f, "Callstack:\n"); + for (std::size_t i = 0; i < size; i++) { + fprintf(f, "%s\n", strings[i]); + } + free(strings); +#endif +} + +void MySignalHandler(int signo, siginfo_t * /*info*/, void * /*context*/) +{ + fprintf(stderr, "Internal error (caught signal %d). Please report this to the cppcheck developers!\n", + signo); + print_stacktrace(stderr); + abort(); +} +#endif + +int CppCheckExecutor::check_wrapper(CppCheck& cppCheck, int argc, const char* const argv[]) +{ +#ifdef _MSC_VER + /* not yet finished + __try { + */ + return check_internal(cppCheck, argc, argv); + /* + } + except() { + return -1; + } + */ +#elif defined(USE_UNIX_SIGNAL_HANDLING) + struct sigaction act = {0}; + act.sa_flags=SA_SIGINFO; + act.sa_sigaction=MySignalHandler; + for (std::size_t s=0; s