mirror of
https://github.com/KjellKod/g3log.git
synced 2024-12-12 18:30:25 +01:00
Merge branch 'clang-improved-crash-handling' of https://github.com/KjellKod/g3log into clang-improved-crash-handling
Conflicts: Build.cmake example/main_fatal_choice.cpp
This commit is contained in:
commit
a8d89b67c8
@ -85,9 +85,6 @@ ENDIF()
|
|||||||
|
|
||||||
add_library(g3logger_shared SHARED ${SRC_FILES})
|
add_library(g3logger_shared SHARED ${SRC_FILES})
|
||||||
set_target_properties(g3logger_shared PROPERTIES LINKER_LANGUAGE CXX)
|
set_target_properties(g3logger_shared PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
IF(APPLE)
|
|
||||||
set_target_properties(g3logger_shared PROPERTIES MACOSX_RPATH TRUE)
|
|
||||||
ENDIF(APPLE)
|
|
||||||
target_link_libraries(g3logger_shared ${PLATFORM_LINK_LIBRIES})
|
target_link_libraries(g3logger_shared ${PLATFORM_LINK_LIBRIES})
|
||||||
|
|
||||||
SET(G3LOG_SHARED_LIBRARY g3logger_shared)
|
SET(G3LOG_SHARED_LIBRARY g3logger_shared)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -34,34 +35,34 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RaiseSIGABRT() {
|
void RaiseSIGABRT() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
|
||||||
raise(SIGABRT);
|
raise(SIGABRT);
|
||||||
|
LOG(DEBUG) << " trigger exit";
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaiseSIGFPE() {
|
void RaiseSIGFPE() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
|
LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
|
||||||
raise(SIGFPE);
|
raise(SIGFPE);
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaiseSIGSEGV() {
|
void RaiseSIGSEGV() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
LOG(DEBUG) << "Exit by SIGSEGV";
|
LOG(DEBUG) << "Exit by SIGSEGV";
|
||||||
raise(SIGSEGV);
|
raise(SIGSEGV);
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaiseSIGILL() {
|
void RaiseSIGILL() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
LOGF(DEBUG, "Exit by %s", "SIGILL");
|
LOGF(DEBUG, "Exit by %s", "SIGILL");
|
||||||
raise(SIGILL);
|
raise(SIGILL);
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RAiseSIGTERM() {
|
void RAiseSIGTERM() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
|
LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
|
||||||
raise(SIGTERM);
|
raise(SIGTERM);
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
@ -69,8 +70,7 @@ namespace
|
|||||||
|
|
||||||
int gShouldBeZero = 1;
|
int gShouldBeZero = 1;
|
||||||
void DivisionByZero() {
|
void DivisionByZero() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit Executing DivisionByZero: gShouldBeZero: " << gShouldBeZero;
|
||||||
std::cout << "Executing DivisionByZero: gShouldBeZero: " << gShouldBeZero << std::endl;
|
|
||||||
LOG(INFO) << "Division by zero is a big no-no";
|
LOG(INFO) << "Division by zero is a big no-no";
|
||||||
int value = 3;
|
int value = 3;
|
||||||
auto test = value / gShouldBeZero;
|
auto test = value / gShouldBeZero;
|
||||||
@ -78,14 +78,14 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IllegalPrintf() {
|
void IllegalPrintf() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
LOG(DEBUG) << "Impending doom due to illeteracy";
|
LOG(DEBUG) << "Impending doom due to illeteracy";
|
||||||
LOGF(INFO, "2nd attempt at ILLEGAL PRINTF_SYNTAX %d EXAMPLE. %s %s", "hello", 1);
|
LOGF(INFO, "2nd attempt at ILLEGAL PRINTF_SYNTAX %d EXAMPLE. %s %s", "hello", 1);
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutOfBoundsArrayIndexing() {
|
void OutOfBoundsArrayIndexing() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
std::vector<int> v;
|
std::vector<int> v;
|
||||||
v[0] = 5;
|
v[0] = 5;
|
||||||
LOG(WARNING) << "Expected to have died by now...";
|
LOG(WARNING) << "Expected to have died by now...";
|
||||||
@ -93,7 +93,7 @@ namespace
|
|||||||
|
|
||||||
|
|
||||||
void AccessViolation() {
|
void AccessViolation() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
char *ptr = 0;
|
char *ptr = 0;
|
||||||
LOG(INFO) << "Death by access violation is imminent";
|
LOG(INFO) << "Death by access violation is imminent";
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
@ -101,12 +101,12 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NoExitFunction() {
|
void NoExitFunction() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
CHECK(false) << "This function should never be called";
|
CHECK(false) << "This function should never be called";
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaiseSIGABRTAndAccessViolation() {
|
void RaiseSIGABRTAndAccessViolation() {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << " trigger exit";
|
||||||
|
|
||||||
auto f1 = std::async(std::launch::async, &RaiseSIGABRT);
|
auto f1 = std::async(std::launch::async, &RaiseSIGABRT);
|
||||||
auto f2 = std::async(std::launch::async, &AccessViolation);
|
auto f2 = std::async(std::launch::async, &AccessViolation);
|
||||||
@ -114,11 +114,44 @@ namespace
|
|||||||
f2.wait();
|
f2.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThrowInt() {
|
|
||||||
throw 1233210;
|
using deathfunc = void (*) (void);
|
||||||
|
void Death_x10000(deathfunc func, std::string funcname) noexcept {
|
||||||
|
LOG(DEBUG) << " trigger exit";
|
||||||
|
std::vector<std::future<void>> asyncs;
|
||||||
|
asyncs.reserve(10000);
|
||||||
|
for (auto idx = 0; idx < 10000; ++idx) {
|
||||||
|
asyncs.push_back(std::async(std::launch::async, func));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& a : asyncs) {
|
||||||
|
a.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << __FUNCTION__ << " unexpected result. Death by " << funcname << " did not crash and exit the system" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Throw() noexcept {
|
||||||
|
LOG(DEBUG) << " trigger exit";
|
||||||
|
std::future<int> empty;
|
||||||
|
empty.get();
|
||||||
|
// --> thows future_error http://en.cppreference.com/w/cpp/thread/future_error
|
||||||
|
// example of std::exceptions can be found here: http://en.cppreference.com/w/cpp/error/exception
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SegFaultAttempt_x10000() noexcept {
|
||||||
|
deathfunc f = []{Throw(); *(char*)0 = 0; char* ptr = 0; *ptr = 1; AccessViolation();};
|
||||||
|
Death_x10000(f, "throw uncaught exception... and then some sigsegv calls");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AccessViolation_x10000() {
|
||||||
|
Death_x10000(&AccessViolation, "AccessViolation");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FailedCHECK() {
|
void FailedCHECK() {
|
||||||
|
LOG(DEBUG) << " trigger exit";
|
||||||
CHECK(false) << "This is fatal";
|
CHECK(false) << "This is fatal";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +166,8 @@ namespace
|
|||||||
|
|
||||||
|
|
||||||
void ExecuteDeathFunction(const bool runInNewThread, int fatalChoice) {
|
void ExecuteDeathFunction(const bool runInNewThread, int fatalChoice) {
|
||||||
std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
|
LOG(DEBUG) << "trigger exit";
|
||||||
|
|
||||||
auto exitFunction = &NoExitFunction;
|
auto exitFunction = &NoExitFunction;
|
||||||
switch (fatalChoice) {
|
switch (fatalChoice) {
|
||||||
case 1: exitFunction = &RaiseSIGABRT; break;
|
case 1: exitFunction = &RaiseSIGABRT; break;
|
||||||
@ -146,8 +180,10 @@ namespace
|
|||||||
case 8: exitFunction = &OutOfBoundsArrayIndexing; break;
|
case 8: exitFunction = &OutOfBoundsArrayIndexing; break;
|
||||||
case 9: exitFunction = &AccessViolation; break;
|
case 9: exitFunction = &AccessViolation; break;
|
||||||
case 10: exitFunction = &RaiseSIGABRTAndAccessViolation; break;
|
case 10: exitFunction = &RaiseSIGABRTAndAccessViolation; break;
|
||||||
case 11: exitFunction = &ThrowInt; break;
|
case 11: exitFunction = &Throw; break;
|
||||||
case 12: exitFunction = &FailedCHECK; break;
|
case 12: exitFunction = &FailedCHECK; break;
|
||||||
|
case 13: exitFunction = &AccessViolation_x10000; break;
|
||||||
|
case 14: exitFunction = &SegFaultAttempt_x10000; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (runInNewThread) {
|
if (runInNewThread) {
|
||||||
@ -203,16 +239,17 @@ namespace
|
|||||||
std::cout << "[8] Out of bounds array indexing " << std::endl;
|
std::cout << "[8] Out of bounds array indexing " << std::endl;
|
||||||
std::cout << "[9] Access violation" << std::endl;
|
std::cout << "[9] Access violation" << std::endl;
|
||||||
std::cout << "[10] Rasing SIGABRT + Access Violation in two separate threads" << std::endl;
|
std::cout << "[10] Rasing SIGABRT + Access Violation in two separate threads" << std::endl;
|
||||||
std::cout << "[11] Just throw (in this thread)" << std::endl;
|
std::cout << "[11] Throw a std::future_error" << std::endl;
|
||||||
std::cout << "[12] Just CHECK(false) (in this thread)" << std::endl;
|
std::cout << "[12] Just CHECK(false) (in this thread)" << std::endl;
|
||||||
|
std::cout << "[13] 10,000 Continious crashes with out of bounds array indexing" << std::endl;
|
||||||
|
std::cout << "[14] 10,000 Continious crashes with segmentation fault attempts" << std::endl;
|
||||||
|
|
||||||
std::cout << std::flush;
|
std::cout << std::flush;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::getline(std::cin, option);
|
std::getline(std::cin, option);
|
||||||
choice = std::stoi(option);
|
choice = std::stoi(option);
|
||||||
if (choice <= 0 || choice > 12) {
|
if (choice <= 0 || choice > 14) {
|
||||||
std::cout << "Invalid choice: [" << option << "\n\n";
|
std::cout << "Invalid choice: [" << option << "\n\n";
|
||||||
} else {
|
} else {
|
||||||
return choice;
|
return choice;
|
||||||
@ -236,9 +273,9 @@ namespace
|
|||||||
|
|
||||||
void breakHere() {
|
void breakHere() {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << __FUNCTION__ << " was reached" << std::endl;
|
oss << "Fatal hook function: " << __FUNCTION__ << ":" << __LINE__ << " was called";
|
||||||
std::cout << oss.str() << std::endl;
|
oss << " through g3::setFatalPreLoggingHook(). setFatalPreLoggingHook should be called AFTER g3::initializeLogging()" << std::endl;
|
||||||
|
LOG(DEBUG) << oss.str();
|
||||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
#endif
|
#endif
|
||||||
@ -246,12 +283,13 @@ void breakHere() {
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto worker = g3::LogWorker::createLogWorker();
|
auto worker = g3::LogWorker::createLogWorker();
|
||||||
auto handle= worker->addDefaultLogger(argv[0], path_to_log_file);
|
auto handle= worker->addDefaultLogger(argv[0], path_to_log_file);
|
||||||
g3::initializeLogging(worker.get());
|
g3::initializeLogging(worker.get());
|
||||||
g3::setFatalPreLoggingHook(&breakHere);
|
g3::setFatalPreLoggingHook(&breakHere);
|
||||||
|
|
||||||
std::future<std::string> log_file_name = handle->call(&g3::FileSink::fileName);
|
std::future<std::string> log_file_name = handle->call(&g3::FileSink::fileName);
|
||||||
|
|
||||||
std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
|
std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
|
||||||
<< "Choose your type of fatal exit, then "
|
<< "Choose your type of fatal exit, then "
|
||||||
<< " read the generated log and backtrace.\n"
|
<< " read the generated log and backtrace.\n"
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#error "crashhandler_unix.cpp used but it's a windows system"
|
#error "crashhandler_unix.cpp used but it's a windows system"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -23,7 +24,8 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
// Linux/Clang, OSX/Clang, OSX/gcc
|
// Linux/Clang, OSX/Clang, OSX/gcc
|
||||||
#if (defined(__clang__) || defined(__APPLE__))
|
#if (defined(__clang__) || defined(__APPLE__))
|
||||||
@ -34,10 +36,35 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
bool shouldDoExit() {
|
||||||
|
static std::atomic<uint64_t> firstExit{0};
|
||||||
|
auto const count = firstExit.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
return (0 == count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void restoreSignalHandler(int signal_number) {
|
||||||
|
std::cerr << "\n\n" << __FUNCTION__ << " " << signal_number << " threadID: " << std::this_thread::get_id() << std::endl;
|
||||||
|
#if !(defined(DISABLE_FATAL_SIGNALHANDLING))
|
||||||
|
struct sigaction action;
|
||||||
|
memset(&action, 0, sizeof (action)); //
|
||||||
|
sigemptyset(&action.sa_mask);
|
||||||
|
action.sa_handler = SIG_DFL; // take default action for the signal
|
||||||
|
sigaction(signal_number, &action, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Dump of stack,. then exit through g3log background worker
|
// Dump of stack,. then exit through g3log background worker
|
||||||
// ALL thanks to this thread at StackOverflow. Pretty much borrowed from:
|
// ALL thanks to this thread at StackOverflow. Pretty much borrowed from:
|
||||||
// Ref: http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
|
// Ref: http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
|
||||||
void signalHandler(int signal_number, siginfo_t *info, void *unused_context) {
|
void signalHandler(int signal_number, siginfo_t *info, void *unused_context) {
|
||||||
|
|
||||||
|
// Only one signal will be allowed past this point
|
||||||
|
if (false == shouldDoExit()) {
|
||||||
|
while (true) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using namespace g3::internal;
|
using namespace g3::internal;
|
||||||
{
|
{
|
||||||
const auto dump = stackdump();
|
const auto dump = stackdump();
|
||||||
@ -74,10 +101,11 @@ namespace g3 {
|
|||||||
// http://stackoverflow.com/questions/6878546/why-doesnt-parent-process-return-to-the-exact-location-after-handling-signal_number
|
// http://stackoverflow.com/questions/6878546/why-doesnt-parent-process-return-to-the-exact-location-after-handling-signal_number
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
bool blockForFatalHandling() {
|
bool shouldBlockForFatalHandling() {
|
||||||
return true; // For windows we will after fatal processing change it to false
|
return true; // For windows we will after fatal processing change it to false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Generate stackdump. Or in case a stackdump was pre-generated and non-empty just use that one
|
/// Generate stackdump. Or in case a stackdump was pre-generated and non-empty just use that one
|
||||||
/// i.e. the latter case is only for Windows and test purposes
|
/// i.e. the latter case is only for Windows and test purposes
|
||||||
std::string stackdump(const char *rawdump) {
|
std::string stackdump(const char *rawdump) {
|
||||||
@ -182,22 +210,16 @@ namespace g3 {
|
|||||||
// --- If LOG(FATAL) or CHECK(false) the signal_number will be SIGABRT
|
// --- If LOG(FATAL) or CHECK(false) the signal_number will be SIGABRT
|
||||||
void exitWithDefaultSignalHandler(const LEVELS &level, g3::SignalType fatal_signal_id) {
|
void exitWithDefaultSignalHandler(const LEVELS &level, g3::SignalType fatal_signal_id) {
|
||||||
const int signal_number = static_cast<int>(fatal_signal_id);
|
const int signal_number = static_cast<int>(fatal_signal_id);
|
||||||
std::cerr << "Exiting due to " << level.text << ", " << signal_number << " " << std::flush;
|
restoreSignalHandler(signal_number);
|
||||||
|
std::cerr << "\n\n" << __FUNCTION__ << ":" << __LINE__ << ". Exiting due to " << level.text << ", " << signal_number << " \n\n" << std::flush;
|
||||||
|
|
||||||
#if !(defined(DISABLE_FATAL_SIGNALHANDLING))
|
|
||||||
struct sigaction action;
|
|
||||||
memset(&action, 0, sizeof (action)); //
|
|
||||||
sigemptyset(&action.sa_mask);
|
|
||||||
action.sa_handler = SIG_DFL; // take default action for the signal
|
|
||||||
sigaction(signal_number, &action, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
kill(getpid(), signal_number);
|
kill(getpid(), signal_number);
|
||||||
abort(); // should never reach this
|
exit(signal_number);
|
||||||
|
|
||||||
}
|
}
|
||||||
} // end g3::internal
|
} // end g3::internal
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Installs FATAL signal handler that is enough to handle most fatal events
|
// Installs FATAL signal handler that is enough to handle most fatal events
|
||||||
// on *NIX systems
|
// on *NIX systems
|
||||||
|
@ -148,11 +148,9 @@ namespace {
|
|||||||
|
|
||||||
namespace g3 {
|
namespace g3 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
// For windows exceptions this might ONCE be set to false, in case of a
|
// For windows exceptions this might ONCE be set to false, in case of a
|
||||||
// windows exceptions and not a signal
|
// windows exceptions and not a signal
|
||||||
bool blockForFatalHandling() {
|
bool shouldBlockForFatalHandling() {
|
||||||
return gBlockForFatal;
|
return gBlockForFatal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ namespace g3 {
|
|||||||
internal::exitWithDefaultSignalHandler(message.get()->_level, message.get()->_signal_id);
|
internal::exitWithDefaultSignalHandler(message.get()->_level, message.get()->_signal_id);
|
||||||
}
|
}
|
||||||
g_logger_instance->fatal(message);
|
g_logger_instance->fatal(message);
|
||||||
while (blockForFatalHandling()) {
|
while (shouldBlockForFatalHandling()) {
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,17 @@
|
|||||||
// implementationsfilen kan vara den samma
|
// implementationsfilen kan vara den samma
|
||||||
namespace g3 {
|
namespace g3 {
|
||||||
|
|
||||||
|
// PUBLIC API:
|
||||||
|
/** Install signal handler that catches FATAL C-runtime or OS signals
|
||||||
|
See the wikipedia site for details http://en.wikipedia.org/wiki/SIGFPE
|
||||||
|
See the this site for example usage: http://www.tutorialspoint.com/cplusplus/cpp_signal_handling.hpptm
|
||||||
|
SIGABRT ABORT (ANSI), abnormal termination
|
||||||
|
SIGFPE Floating point exception (ANSI)
|
||||||
|
SIGILL ILlegal instruction (ANSI)
|
||||||
|
SIGSEGV Segmentation violation i.e. illegal memory reference
|
||||||
|
SIGTERM TERMINATION (ANSI) */
|
||||||
|
void installCrashHandler();
|
||||||
|
|
||||||
|
|
||||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
typedef unsigned long SignalType;
|
typedef unsigned long SignalType;
|
||||||
@ -35,30 +46,18 @@ namespace g3 {
|
|||||||
* only in the case of Windows exceptions (not fatal signals)
|
* only in the case of Windows exceptions (not fatal signals)
|
||||||
* are we interested in changing this from false to true to
|
* are we interested in changing this from false to true to
|
||||||
* help any other exceptions handler work with 'EXCEPTION_CONTINUE_SEARCH'*/
|
* help any other exceptions handler work with 'EXCEPTION_CONTINUE_SEARCH'*/
|
||||||
bool blockForFatalHandling();
|
bool shouldBlockForFatalHandling();
|
||||||
|
|
||||||
/** \return signal_name Ref: signum.hpp and \ref installSignalHandler
|
/** \return signal_name Ref: signum.hpp and \ref installSignalHandler
|
||||||
* or for Windows exception name */
|
* or for Windows exception name */
|
||||||
std::string exitReasonName(const LEVELS &level, g3::SignalType signal_number);
|
std::string exitReasonName(const LEVELS& level, g3::SignalType signal_number);
|
||||||
|
|
||||||
/** return calling thread's stackdump*/
|
/** return calling thread's stackdump*/
|
||||||
std::string stackdump(const char *dump = nullptr);
|
std::string stackdump(const char* dump = nullptr);
|
||||||
|
|
||||||
/** Re-"throw" a fatal signal, previously caught. This will exit the application
|
/** Re-"throw" a fatal signal, previously caught. This will exit the application
|
||||||
* This is an internal only function. Do not use it elsewhere. It is triggered
|
* This is an internal only function. Do not use it elsewhere. It is triggered
|
||||||
* from g3log, g3LogWorker after flushing messages to file */
|
* from g3log, g3LogWorker after flushing messages to file */
|
||||||
void exitWithDefaultSignalHandler(const LEVELS &level, g3::SignalType signal_number);
|
void exitWithDefaultSignalHandler(const LEVELS& level, g3::SignalType signal_number);
|
||||||
} // end g3::internal
|
} // end g3::internal
|
||||||
|
} // g3
|
||||||
|
|
||||||
// PUBLIC API:
|
|
||||||
/** Install signal handler that catches FATAL C-runtime or OS signals
|
|
||||||
See the wikipedia site for details http://en.wikipedia.org/wiki/SIGFPE
|
|
||||||
See the this site for example usage: http://www.tutorialspoint.com/cplusplus/cpp_signal_handling.hpptm
|
|
||||||
SIGABRT ABORT (ANSI), abnormal termination
|
|
||||||
SIGFPE Floating point exception (ANSI)
|
|
||||||
SIGILL ILlegal instruction (ANSI)
|
|
||||||
SIGSEGV Segmentation violation i.e. illegal memory reference
|
|
||||||
SIGTERM TERMINATION (ANSI) */
|
|
||||||
void installCrashHandler();
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user