diff options
Diffstat (limited to 'tests/backtrace/driver.cxx')
-rw-r--r-- | tests/backtrace/driver.cxx | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/tests/backtrace/driver.cxx b/tests/backtrace/driver.cxx new file mode 100644 index 0000000..5fd9223 --- /dev/null +++ b/tests/backtrace/driver.cxx @@ -0,0 +1,97 @@ +// file : tests/backtrace/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef _WIN32 +# include <sys/resource.h> // setrlimit() +#endif + +#include <cassert> + +#ifndef __cpp_lib_modules_ts +#include <string> +#include <iostream> +#include <exception> // set_terminate(), terminate_handler +#include <system_error> +#else +import std.io; +#endif + +// Other includes. + +#ifdef __cpp_modules_ts +#ifdef __cpp_lib_modules_ts +import std.core; +#endif +import butl.process; +import butl.backtrace; +#else +#include <libbutl/process.mxx> +#include <libbutl/backtrace.mxx> +#endif + +using namespace std; +using namespace butl; + +namespace test +{ + // Note: is not static to make sure the stack frame is not optimized out. + // + int + func () + { + throw system_error (EINVAL, generic_category ()); + } +} + +static terminate_handler def_term_handler; + +// Usage: argv[0] [-c] +// +// Print the backtrace for an unhandled exception. +// +// -c +// Run as a child process that sets up the backtrace-printing terminate +// handler and throws unhandled exception. +int +main (int argc, const char* argv[]) +{ + // Not to cause the testscript to fail due to the abnormal test driver + // termination, delegate the unhandled exception backtrace printing to the + // child process. + // + bool child (false); + for (int i (1); i != argc; ++i) + { + string o (argv[i]); + + if (o == "-c") + child = true; + else + assert (false); + } + + if (child) + { + // Disable dumping core file on POSIX. + // +#ifndef _WIN32 + struct rlimit rlim {0, 0}; + assert (setrlimit (RLIMIT_CORE, &rlim) == 0); +#endif + + def_term_handler = set_terminate ([]() + { + cerr << backtrace (); + + if (def_term_handler != nullptr) + def_term_handler (); + }); + + return test::func (); + } + + // Report failure with non-zero code if child succeeds. + // + return process_run (0, 1, 2, argv[0], "-c") ? 1 : 0; +} |