mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
Allow setting a default debug action
Helps avoiding user interaction when running a batch of unit tests.
This commit is contained in:
parent
eaf38abf17
commit
1d805807e9
2 changed files with 60 additions and 18 deletions
|
@ -75,32 +75,62 @@ bool is_debug_enabled(const char * tag) {
|
|||
return g_enabled_debug_tags->contains(tag);
|
||||
}
|
||||
|
||||
atomic<debug_action> g_default_debug_action(debug_action::ask);
|
||||
|
||||
debug_action get_default_debug_action() {
|
||||
return g_default_debug_action;
|
||||
}
|
||||
|
||||
void set_default_debug_action(debug_action a) {
|
||||
g_default_debug_action = a;
|
||||
}
|
||||
|
||||
debug_action ask_debug_action(std::istream& in) {
|
||||
std::cerr << "(C)ontinue, (A)bort, (S)top, (T)hrow exception, Invoke (G)DB\n";
|
||||
char result;
|
||||
bool ok = bool(in >> result);
|
||||
if (!ok)
|
||||
exit(ERR_INTERNAL_FATAL); // happens if std::cin is eof or unattached.
|
||||
switch(result) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
return debug_action::cont;
|
||||
case 'A':
|
||||
case 'a':
|
||||
return debug_action::abort;
|
||||
case 'S':
|
||||
case 's':
|
||||
return debug_action::stop;
|
||||
case 't':
|
||||
case 'T':
|
||||
return debug_action::throw_exception;
|
||||
case 'G':
|
||||
case 'g':
|
||||
return debug_action::invoke_debugger;
|
||||
default:
|
||||
std::cerr << "INVALID COMMAND\n";
|
||||
return debug_action::ask;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(NO_Z3_DEBUGGER)
|
||||
void invoke_gdb() {
|
||||
char buffer[1024];
|
||||
int * x = nullptr;
|
||||
int *x = nullptr;
|
||||
debug_action a = get_default_debug_action();
|
||||
for (;;) {
|
||||
std::cerr << "(C)ontinue, (A)bort, (S)top, (T)hrow exception, Invoke (G)DB\n";
|
||||
char result;
|
||||
bool ok = bool(std::cin >> result);
|
||||
if (!ok) exit(ERR_INTERNAL_FATAL); // happens if std::cin is eof or unattached.
|
||||
switch(result) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
switch (a) {
|
||||
case debug_action::cont:
|
||||
return;
|
||||
case 'A':
|
||||
case 'a':
|
||||
case debug_action::abort:
|
||||
exit(1);
|
||||
case 'S':
|
||||
case 's':
|
||||
case debug_action::stop:
|
||||
// force seg fault...
|
||||
*x = 0;
|
||||
return;
|
||||
case 't':
|
||||
case 'T':
|
||||
case debug_action::throw_exception:
|
||||
throw default_exception("assertion violation");
|
||||
case 'G':
|
||||
case 'g':
|
||||
case debug_action::invoke_debugger:
|
||||
sprintf(buffer, "gdb -nw /proc/%d/exe %d", getpid(), getpid());
|
||||
std::cerr << "invoking GDB...\n";
|
||||
if (system(buffer) == 0) {
|
||||
|
@ -109,12 +139,13 @@ void invoke_gdb() {
|
|||
else {
|
||||
std::cerr << "error starting GDB...\n";
|
||||
// forcing seg fault.
|
||||
int * x = nullptr;
|
||||
int *x = nullptr;
|
||||
*x = 0;
|
||||
}
|
||||
return;
|
||||
case debug_action::ask:
|
||||
default:
|
||||
std::cerr << "INVALID COMMAND\n";
|
||||
a = ask_debug_action(std::cin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,17 @@ Revision History:
|
|||
void enable_assertions(bool f);
|
||||
bool assertions_enabled();
|
||||
|
||||
enum class debug_action {
|
||||
ask,
|
||||
cont,
|
||||
abort,
|
||||
stop,
|
||||
throw_exception,
|
||||
invoke_debugger,
|
||||
};
|
||||
debug_action get_default_debug_action();
|
||||
void set_default_debug_action(debug_action a);
|
||||
|
||||
#include "util/error_codes.h"
|
||||
#include "util/warning.h"
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue