#include <exception>
#include <string.h>
#include <signal.h>
+#include <sys/resource.h>
#include "util/Assert.h"
#include "util/exception.h"
namespace CVC4 {
namespace main {
+size_t cvc4StackSize;
+void* cvc4StackBase;
+
/**
* If true, will not spin on segfault even when CVC4_DEBUG is on.
* Useful for nightly regressions, noninteractive performance runs
}
/** Handler for SIGSEGV (segfault). */
-void segv_handler(int sig, siginfo_t* info, void*) {
+void segv_handler(int sig, siginfo_t* info, void* c) {
+ uintptr_t extent = reinterpret_cast<uintptr_t>(cvc4StackBase) - cvc4StackSize;
+ uintptr_t addr = reinterpret_cast<uintptr_t>(info->si_addr);
#ifdef CVC4_DEBUG
fprintf(stderr, "CVC4 suffered a segfault in DEBUG mode.\n");
+ cerr << "Offending address is " << info->si_addr << endl;
+ //cerr << "base is " << (void*)cvc4StackBase << endl;
+ //cerr << "size is " << cvc4StackSize << endl;
+ //cerr << "extent is " << (void*)extent << endl;
+ if(addr >= extent && addr <= extent + 10*1024) {
+ cerr << "Looks like this is likely due to stack overflow." << endl
+ << "You might consider increasing the limit with `ulimit -s' or equivalent." << endl;
+ } else if(addr < 10*1024) {
+ cerr << "Looks like a NULL pointer was dereferenced." << endl;
+ }
+
if(segvNoSpin) {
fprintf(stderr, "No-spin requested, aborting...\n");
+ if(options.statistics) {
+ StatisticsRegistry::flushStatistics(cerr);
+ }
abort();
} else {
fprintf(stderr, "Spinning so that a debugger can be connected.\n");
}
#else /* CVC4_DEBUG */
fprintf(stderr, "CVC4 suffered a segfault.\n");
+ cerr << "Offending address is " << info->si_addr << endl;
+ if(addr >= extent && addr <= extent + 10*1024) {
+ cerr << "Looks like this is likely due to stack overflow." << endl
+ << "You might consider increasing the limit with `ulimit -s' or equivalent." << endl;
+ } else if(addr < 10*1024) {
+ cerr << "Looks like a NULL pointer was dereferenced." << endl;
+ }
if(options.statistics) {
StatisticsRegistry::flushStatistics(cerr);
}
}
/** Initialize the driver. Sets signal handlers for SIGINT and SIGSEGV. */
-void cvc4_init() throw() {
+void cvc4_init() throw(Exception) {
+ stack_t ss;
+ ss.ss_sp = malloc(SIGSTKSZ);
+ if(ss.ss_sp == NULL) {
+ throw Exception("Can't malloc() space for a signal stack");
+ }
+ ss.ss_size = SIGSTKSZ;
+ ss.ss_flags = 0;
+ if(sigaltstack(&ss, NULL) == -1) {
+ throw Exception(string("sigaltstack() failure: ") + strerror(errno));
+ }
+ struct rlimit limit;
+ if(getrlimit(RLIMIT_STACK, &limit)) {
+ throw Exception(string("getrlimit() failure: ") + strerror(errno));
+ }
+ if(limit.rlim_cur != limit.rlim_max) {
+ limit.rlim_cur = limit.rlim_max;
+ if(setrlimit(RLIMIT_STACK, &limit)) {
+ throw Exception(string("setrlimit() failure: ") + strerror(errno));
+ }
+ if(getrlimit(RLIMIT_STACK, &limit)) {
+ throw Exception(string("getrlimit() failure: ") + strerror(errno));
+ }
+ }
+ cvc4StackSize = limit.rlim_cur;
+ cvc4StackBase = &ss;
+
struct sigaction act1;
act1.sa_sigaction = sigint_handler;
act1.sa_flags = SA_SIGINFO;
struct sigaction act3;
act3.sa_sigaction = segv_handler;
- act3.sa_flags = SA_SIGINFO;
+ act3.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigemptyset(&act3.sa_mask);
if(sigaction(SIGSEGV, &act3, NULL)) {
throw Exception(string("sigaction(SIGSEGV) failure: ") + strerror(errno));