irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

irods_stacktrace.cpp
Go to the documentation of this file.
1 #include "irods_stacktrace.hpp"
2 #include "rodsErrorTable.h"
3 #include "irods_log.hpp"
4 
5 #include <sstream>
6 
7 #include <execinfo.h>
8 #include <cstdlib>
9 #include <cxxabi.h>
10 namespace {
11  class stacktrace_resolution_exception : public std::runtime_error
12  {
13  public :
14  stacktrace_resolution_exception(const std::string& message) :
15  std::runtime_error(message) {}
16  };
17 }
18 namespace irods {
19  stacktrace::stacktrace() : backtrace_(max_stack_size) {
20  size_ = backtrace( backtrace_.data(), max_stack_size );
21  }
22 
23  //this is very, very, very slow. do not call it more
24  //than once per stacktrace object
26  if ( size_ == 0 ) {
27  throw stacktrace_resolution_exception("Stack trace is empty");
28  }
29 
30  char** symbols = backtrace_symbols( backtrace_.data(), size_ );
31  if ( !symbols ) {
32  throw stacktrace_resolution_exception("Cannot generate stack symbols");
33  }
34 
35  stacklist stack;
36  for ( int i = 1; i < size_; ++i ) {
37  char* symbol = symbols[i];
38  if ( !symbol ) {
39  free( symbols );
40  throw stacktrace_resolution_exception("Corrupt stack trace. Symbol is NULL.");
41  }
42  std::string demangled;
43  std::string offset;
44  demangle_symbol( symbol, demangled, offset );
46  entry.function = demangled;
47  entry.offset = offset;
48  entry.address = backtrace_[i];
49  stack.push_back( entry );
50  }
51  free( symbols );
52  return stack;
53  }
54 
55  const std::string& stacktrace::dump() const {
56  if ( !dump_ ) {
57  try {
58  stacklist stack = resolve_stack();
59 
60  uint64_t max_offset_length{0};
61  for (const auto& entry : stack) {
62  if (entry.offset.length() > max_offset_length) {
63  max_offset_length = entry.offset.length();
64  }
65  }
66  std::stringstream out_stream;
67  out_stream << std::endl << "Dumping stack trace" << std::endl;
68  uint64_t frame_index{0};
69  for (auto it = std::begin(stack); it != std::end(stack); ++it, ++frame_index) {
70  const auto& entry{*it};
71  out_stream << "<" << frame_index << ">";
72  out_stream << "\t" << "Offset: " << entry.offset;
73  const uint64_t pad_amount{max_offset_length - entry.offset.length()};
74  for (uint64_t i=0; i<pad_amount; ++i) {
75  out_stream << " ";
76  }
77  out_stream << "\t" << "Address: " << entry.address;
78  out_stream << "\t" << entry.function;
79  out_stream << std::endl;
80  }
81  out_stream << std::endl;
82  dump_.reset(out_stream.str());
83  } catch ( const stacktrace_resolution_exception& e ) {
84  dump_.reset( e.what() );
85  }
86  }
87  return *dump_;
88  }
89 
91  const std::string& _symbol,
92  std::string& _rtn_name,
93  std::string& _rtn_offset ) const {
94  error result = SUCCESS();
95  _rtn_name = _symbol; // if we cannot demangle the symbol return the original.
96  _rtn_offset.clear();
97 
98  // find the open paren
99  size_t startpos = _symbol.find( "(" );
100  size_t offsetpos = _symbol.find( "+", startpos );
101  size_t nameendpos = _symbol.find( ")", startpos );
102 
103  if ( startpos != std::string::npos && nameendpos != std::string::npos ) {
104  ++startpos;
105  std::string name_symbol;
106  std::string offset_string;
107  if ( offsetpos != std::string::npos ) { // handle the case where there is no offset
108  name_symbol = _symbol.substr( startpos, offsetpos - startpos );
109  ++offsetpos;
110  offset_string = _symbol.substr( offsetpos, nameendpos - offsetpos );
111  }
112  else {
113  name_symbol = _symbol.substr( startpos, nameendpos - startpos );
114  }
115  char* name_buffer;
116  int status;
117  name_buffer = abi::__cxa_demangle( name_symbol.c_str(), NULL, NULL, &status );
118  if ( status == 0 ) {
119  _rtn_name = name_buffer;
120  if ( !offset_string.empty() ) {
121  _rtn_offset = offset_string;
122  }
123  free( name_buffer );
124  }
125 
126  }
127  }
128 
129 }; // namespace irods
NULL
#define NULL
Definition: rodsDef.h:70
irods::stacktrace::dump
const std::string & dump() const
Definition: irods_stacktrace.cpp:55
irods::stacktrace::demangle_symbol
void demangle_symbol(const std::string &_symbol, std::string &_rtn_name, std::string &_rtn_offset) const
Definition: irods_stacktrace.cpp:90
irods::stacktrace::stacktrace
stacktrace()
Definition: irods_stacktrace.cpp:19
irods_stacktrace.hpp
irods::experimental::filesystem::client::end
auto end(const collection_iterator &) noexcept -> const collection_iterator
Definition: collection_iterator.hpp:88
SUCCESS
#define SUCCESS()
Definition: irods_error.hpp:121
irods::experimental::filesystem::client::begin
auto begin(collection_iterator _iter) noexcept -> collection_iterator
Definition: collection_iterator.hpp:83
irods::stacktrace::stacklist
std::vector< stack_entry_t > stacklist
Definition: irods_stacktrace.hpp:28
irods::stacktrace::dump_
boost::optional< std::string > dump_
Definition: irods_stacktrace.hpp:35
irods
Definition: apiHandler.hpp:35
terminate_irods_processes.e
e
Definition: terminate_irods_processes.py:19
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
irods::error
Definition: irods_error.hpp:23
irods::stacktrace::size_
int size_
Definition: irods_stacktrace.hpp:34
entry
Definition: ruleAdmin.cpp:22
irods::stacktrace::resolve_stack
stacklist resolve_stack() const
Definition: irods_stacktrace.cpp:25
rodsErrorTable.h
irods::stacktrace::stack_entry_s
Definition: irods_stacktrace.hpp:22
irods::stacktrace::backtrace_
std::vector< void * > backtrace_
Definition: irods_stacktrace.hpp:33
irods_log.hpp
irods::stacktrace::max_stack_size
static const int max_stack_size
Definition: irods_stacktrace.hpp:17