Scarab  v2.4.11
Project 8 C++ Utility Library
terminate.cc
Go to the documentation of this file.
1 /*
2  * terminate.cc
3  *
4  * Created on: May 23, 2017
5  * Author: N.S. Oblath
6  */
7 
8 // stack trace upon termination has not been implemented for Windows
9 #ifndef _WIN32
10 
11 #include "terminate.hh"
12 
13 #include "logger.hh"
14 
15 //#include <boost/core/demangle.hpp>
16 
17 #include <execinfo.h>
18 //#include <signal.h>
19 #include <string.h>
20 
21 //#include <cstdlib>
22 #include <mutex>
23 #include <stdexcept>
24 
25 namespace {
26  // invoke set_terminate as part of global constant initialization
27  static const bool SET_TERMINATE = std::set_terminate( scarab::terminate );
28 }
29 
30 LOGGER( slog, "terminate" );
31 
32 namespace scarab
33 {
34  // Option 1: Use the terminate() function
35  void terminate()
36  {
37  static std::mutex t_using_terminate;
38  std::unique_lock< std::mutex > t_terminate_locked( t_using_terminate );
39 
40  static bool t_tried_throw = false;
41 
42  try
43  {
44  // try once to re-throw currently active exception
45  if( ! t_tried_throw )
46  {
47  t_tried_throw = true;
48  throw;
49  }
50  }
51  catch( const std::exception &e )
52  {
53  LERROR( slog, "Caught unhandled exception. what(): " << e.what() );
54  }
55  catch (...)
56  {
57  LERROR( slog, "Caught unknown (non-std::exception) & unhandled exception." );
58  }
59 
60  void* t_bt_array[50];
61  int size = backtrace( t_bt_array, 50 );
62 
63  LERROR( slog, "Backtrace from terminate() returned "
64  << size << " frames\n" );
65 
66  char** t_messages = backtrace_symbols( t_bt_array, size );
67 
68  std::stringstream t_bt_str;
69  for( int i = 0; i < size && t_messages != nullptr; ++i )
70  {
71  t_bt_str << "[bt]: (" << i << ") " << t_messages[i] << '\n';
72  }
73  LERROR( slog, "Backtrace:\n" << t_bt_str.str() );
74 
75  free( t_messages );
76 
77  abort();
78  }
79 
80  // Option 2: Handle SIGABRT
81 /*
82  void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
83  {
84  LERROR( slog, "signal " << sig_num
85  << " (" << strsignal(sig_num) << "), address is "
86  << info->si_addr );//<< " from "
87  //<< caller_address );
88 
89  void* array[50];
90  int size = backtrace(array, 50);
91 
92  LERROR(slog, "Backtrace from signal handler returned " << size << " frames\n" );
93 
94  char** messages = backtrace_symbols(array, size);
95 
96  // skip first stack frame (points here)
97  std::stringstream bt_str;
98  for( int i = 1; i < size && messages != NULL; ++i )
99  {
100  bt_str << "[bt]: (" << i << ") " << messages[i] << '\n';
101  }
102  LERROR( slog, "Backtrace:\n" << bt_str.str() );
103 
104  free(messages);
105 
106  exit(EXIT_FAILURE);
107  }
108 */
109 
110 } /* namespace scarab */
111 
112 #endif /* ifndef _WIN32 */
#define LERROR(...)
Definition: logger.hh:370
Contains the logger class and macros, based on Kasper&#39;s KLogger class.
LOGGER(slog, "terminate")
void terminate()
Definition: terminate.cc:35