Skip to content

Commit 825bb0f

Browse files
amai2012danmar
authored andcommitted
Fixed cppcheck-opensource#5286 (Add signal/exception handling to cppcheck and cppcheck-gui)
1 parent cba1879 commit 825bb0f

5 files changed

Lines changed: 119 additions & 1 deletion

File tree

cli/cmdlineparser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
132132
else if (std::strcmp(argv[i], "--debug-fp") == 0)
133133
_settings->debugFalsePositive = true;
134134

135+
// (Experimental) exception handling inside cppcheck client
136+
else if (std::strcmp(argv[i], "--exception-handling") == 0)
137+
_settings->exceptionHandling = true;
138+
135139
// Inconclusive checking (still in testing phase)
136140
else if (std::strcmp(argv[i], "--inconclusive") == 0)
137141
_settings->inconclusive = true;

cli/cppcheckexecutor.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@
3232
#include <algorithm>
3333
#include <climits>
3434

35+
#if defined(__GNUC__)
36+
#define USE_UNIX_SIGNAL_HANDLING
37+
#include <execinfo.h>
38+
#endif
39+
40+
#ifdef USE_UNIX_SIGNAL_HANDLING
41+
#include <signal.h>
42+
#include <stdio.h>
43+
#endif
44+
45+
#ifdef _MSC_VER
46+
#include <Windows.h>
47+
#include <excpt.h>
48+
#endif
49+
3550
CppCheckExecutor::CppCheckExecutor()
3651
: _settings(0), time1(0), errorlist(false)
3752
{
@@ -156,6 +171,83 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
156171
return EXIT_FAILURE;
157172
}
158173

174+
if (cppCheck.settings().exceptionHandling) {
175+
return check_wrapper(cppCheck, argc, argv);
176+
} else {
177+
return check_internal(cppCheck, argc, argv);
178+
}
179+
}
180+
181+
#if defined(USE_UNIX_SIGNAL_HANDLING)
182+
extern "C" void MySignalHandler(int signo, siginfo_t *info, void *context);
183+
184+
/* (declare this list here, so it may be used in signal handlers in addition to main())
185+
* A list of signals available in ISO C
186+
* Check out http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
187+
* For now we only want to detect abnormal behaviour for a few selected signals:
188+
*/
189+
static const int listofsignals[] = {
190+
/* don't care: SIGABRT, */
191+
SIGFPE,
192+
SIGILL,
193+
SIGINT,
194+
SIGSEGV,
195+
/* don't care: SIGTERM */
196+
};
197+
198+
static void print_stacktrace(FILE* f)
199+
{
200+
#if defined(__GNUC__)
201+
void *array[50]= {0};
202+
size_t size = backtrace(array, int(sizeof(array)/sizeof(array[0])));
203+
char **strings = backtrace_symbols(array, (int)size);
204+
fprintf(f, "Callstack:\n");
205+
for (std::size_t i = 0; i < size; i++) {
206+
fprintf(f, "%s\n", strings[i]);
207+
}
208+
free(strings);
209+
#endif
210+
}
211+
212+
void MySignalHandler(int signo, siginfo_t * /*info*/, void * /*context*/)
213+
{
214+
fprintf(stderr, "Internal error (caught signal %d). Please report this to the cppcheck developers!\n",
215+
signo);
216+
print_stacktrace(stderr);
217+
abort();
218+
}
219+
#endif
220+
221+
int CppCheckExecutor::check_wrapper(CppCheck& cppCheck, int argc, const char* const argv[])
222+
{
223+
#ifdef _MSC_VER
224+
/* not yet finished
225+
__try {
226+
*/
227+
return check_internal(cppCheck, argc, argv);
228+
/*
229+
}
230+
except() {
231+
return -1;
232+
}
233+
*/
234+
#elif defined(USE_UNIX_SIGNAL_HANDLING)
235+
struct sigaction act = {0};
236+
act.sa_flags=SA_SIGINFO;
237+
act.sa_sigaction=MySignalHandler;
238+
for (std::size_t s=0; s<sizeof(listofsignals)/sizeof(listofsignals[0]); ++s) {
239+
sigaction(listofsignals[s], &act, NULL);
240+
}
241+
return check_internal(cppCheck, argc, argv);
242+
#else
243+
return check_internal(cppCheck, argc, argv);
244+
#endif
245+
}
246+
247+
int CppCheckExecutor::check_internal(CppCheck& cppCheck, int /*argc*/, const char* const argv[])
248+
{
249+
Settings& settings = cppCheck.settings();
250+
_settings = &settings;
159251
bool std = settings.library.load(argv[0], "std.cfg");
160252
bool posix = true;
161253
if (settings.standards.posix)

cli/cppcheckexecutor.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,25 @@ class CppCheckExecutor : public ErrorLogger {
108108

109109
private:
110110

111+
/**
112+
* Wrapper around check_internal
113+
* - installs optional platform dependent signal handling
114+
*
115+
**/
116+
int check_wrapper(CppCheck& cppCheck, int argc, const char* const argv[]);
117+
118+
/**
119+
* Starts the checking.
120+
*
121+
* @param argc from main()
122+
* @param argv from main()
123+
* @return EXIT_FAILURE if arguments are invalid or no input files
124+
* were found.
125+
* If errors are found and --error-exitcode is used,
126+
* given value is returned instead of default 0.
127+
* If no errors are found, 0 is returned.
128+
*/
129+
int check_internal(CppCheck& cppCheck, int argc, const char* const argv[]);
111130
/**
112131
* Pointer to current settings; set while check() is running.
113132
*/

lib/settings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
Settings::Settings()
2727
: _terminate(false),
28-
debug(false), debugwarnings(false), debugFalsePositive(false),
28+
debug(false), debugwarnings(false), debugFalsePositive(false), exceptionHandling(false),
2929
inconclusive(false), experimental(false),
3030
_errorsOnly(false),
3131
_inlineSuppressions(false),

lib/settings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class CPPCHECKLIB Settings {
6363
/** @brief Is --debug-fp given? */
6464
bool debugFalsePositive;
6565

66+
/** @brief Is --exception-handling given */
67+
bool exceptionHandling;
68+
6669
/** @brief Inconclusive checks */
6770
bool inconclusive;
6871

0 commit comments

Comments
 (0)