Fixed #5286 (Add signal/exception handling to cppcheck and cppcheck-gui)
This commit is contained in:
parent
cba1879fee
commit
825bb0f027
|
@ -132,6 +132,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
||||||
else if (std::strcmp(argv[i], "--debug-fp") == 0)
|
else if (std::strcmp(argv[i], "--debug-fp") == 0)
|
||||||
_settings->debugFalsePositive = true;
|
_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)
|
// Inconclusive checking (still in testing phase)
|
||||||
else if (std::strcmp(argv[i], "--inconclusive") == 0)
|
else if (std::strcmp(argv[i], "--inconclusive") == 0)
|
||||||
_settings->inconclusive = true;
|
_settings->inconclusive = true;
|
||||||
|
|
|
@ -32,6 +32,21 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define USE_UNIX_SIGNAL_HANDLING
|
||||||
|
#include <execinfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_UNIX_SIGNAL_HANDLING
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <excpt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
CppCheckExecutor::CppCheckExecutor()
|
CppCheckExecutor::CppCheckExecutor()
|
||||||
: _settings(0), time1(0), errorlist(false)
|
: _settings(0), time1(0), errorlist(false)
|
||||||
{
|
{
|
||||||
|
@ -156,6 +171,83 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
||||||
return EXIT_FAILURE;
|
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<sizeof(listofsignals)/sizeof(listofsignals[0]); ++s) {
|
||||||
|
sigaction(listofsignals[s], &act, NULL);
|
||||||
|
}
|
||||||
|
return check_internal(cppCheck, argc, argv);
|
||||||
|
#else
|
||||||
|
return check_internal(cppCheck, argc, argv);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int CppCheckExecutor::check_internal(CppCheck& cppCheck, int /*argc*/, const char* const argv[])
|
||||||
|
{
|
||||||
|
Settings& settings = cppCheck.settings();
|
||||||
|
_settings = &settings;
|
||||||
bool std = settings.library.load(argv[0], "std.cfg");
|
bool std = settings.library.load(argv[0], "std.cfg");
|
||||||
bool posix = true;
|
bool posix = true;
|
||||||
if (settings.standards.posix)
|
if (settings.standards.posix)
|
||||||
|
|
|
@ -108,6 +108,25 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around check_internal
|
||||||
|
* - installs optional platform dependent signal handling
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
int check_wrapper(CppCheck& cppCheck, int argc, const char* const argv[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the checking.
|
||||||
|
*
|
||||||
|
* @param argc from main()
|
||||||
|
* @param argv from main()
|
||||||
|
* @return EXIT_FAILURE if arguments are invalid or no input files
|
||||||
|
* were found.
|
||||||
|
* If errors are found and --error-exitcode is used,
|
||||||
|
* given value is returned instead of default 0.
|
||||||
|
* If no errors are found, 0 is returned.
|
||||||
|
*/
|
||||||
|
int check_internal(CppCheck& cppCheck, int argc, const char* const argv[]);
|
||||||
/**
|
/**
|
||||||
* Pointer to current settings; set while check() is running.
|
* Pointer to current settings; set while check() is running.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
Settings::Settings()
|
Settings::Settings()
|
||||||
: _terminate(false),
|
: _terminate(false),
|
||||||
debug(false), debugwarnings(false), debugFalsePositive(false),
|
debug(false), debugwarnings(false), debugFalsePositive(false), exceptionHandling(false),
|
||||||
inconclusive(false), experimental(false),
|
inconclusive(false), experimental(false),
|
||||||
_errorsOnly(false),
|
_errorsOnly(false),
|
||||||
_inlineSuppressions(false),
|
_inlineSuppressions(false),
|
||||||
|
|
|
@ -63,6 +63,9 @@ public:
|
||||||
/** @brief Is --debug-fp given? */
|
/** @brief Is --debug-fp given? */
|
||||||
bool debugFalsePositive;
|
bool debugFalsePositive;
|
||||||
|
|
||||||
|
/** @brief Is --exception-handling given */
|
||||||
|
bool exceptionHandling;
|
||||||
|
|
||||||
/** @brief Inconclusive checks */
|
/** @brief Inconclusive checks */
|
||||||
bool inconclusive;
|
bool inconclusive;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue