OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
print_stack.hpp
1 /*
2  * print_stack.hpp
3  *
4  * Created on: Feb 12, 2017
5  * Author: i-bird
6  */
7 
8 #ifndef OPENFPM_DATA_SRC_UTIL_PRINT_STACK_HPP_
9 #define OPENFPM_DATA_SRC_UTIL_PRINT_STACK_HPP_
10 
11 #include <sstream>
12 #include <cstdio>
13 #include <iostream>
14 #include <memory>
15 #include <stdexcept>
16 #include <string>
17 #include <array>
18 #ifndef __CYGWIN__
19 #include <execinfo.h>
20 #endif
21 
22 extern std::string program_name;
23 
28 static inline std::string exec(const char* cmd)
29 {
30  std::array<char, 128> buffer;
31  std::string result;
32  std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
33  if (!pipe) throw std::runtime_error("popen() failed!");
34  while (!feof(pipe.get()))
35  {
36  if (fgets(buffer.data(), 128, pipe.get()) != NULL)
37  result += buffer.data();
38  }
39  return result;
40 }
41 
46 static inline void print_stack()
47 {
48 #if defined(PRINT_STACKTRACE) && !defined(__CYGWIN__)
49 
50  void *trace[256];
51 
52  int ncall = backtrace(trace,256);
53  char ** messages = backtrace_symbols(trace, ncall);
54 
55  std::stringstream str;
56 
57  str << "\033[1;31m*******************************************\033[0m" << std::endl;
58  str << "\033[1;31m*********** STACK TRACE *******************\033[0m" << std::endl;
59  str << "\033[1;31m*******************************************\033[0m" << std::endl;
60 
61  str << "\033[1mThe stack trace indicate where in the code happened the error the error " <<
62  "is in general detected inside the library. In order to find the position " <<
63  "in your code, follow from top to bottom the list of calls until you find " <<
64  "a source code familiar to you.\033[0m" << std::endl;
65 
66  std::string translators[]={"eu-addr2line","addr2line"};
67  std::string translator;
68 
69  for (size_t i = 0 ; i < sizeof(translators)/sizeof(std::string) ; i++)
70  {
71  // for for the best address to source code translator
72  char syscom[256];
73  sprintf(syscom,"%s --version",translators[i].c_str());
74 
75  std::string ss = exec(syscom);
76  size_t found = ss.find("command not found");
77  if (found == std::string::npos)
78  {
79  // command exist
80  translator = translators[i];
81  str << "Using translator: " << translator << std::endl;
82  break;
83  }
84  }
85 
86  if (translator.size() == 0)
87  {
88  str << "In order to have a more detailed stack-trace with function name and precise location in the source code" <<
89  "Please install one of the following utils: ";
90 
91  str << translators[0];
92 
93  for (size_t i = 1 ; i < sizeof(translators)/sizeof(std::string) ; i++)
94  str << "," << translators[i];
95  }
96 
97  for (int i = 0 ; i < ncall ; i++)
98  {
99  str << "\033[1m" << "CALL(" << i << ")" << "\033[0m" << " Address: " << trace[i] << " " << messages[i] << " ";
100 
101  if (translator.size() != 0)
102  {
103  char syscom[256];
104  sprintf(syscom,"%s %p -f --demangle -e %s",translator.c_str(), trace[i],program_name.c_str()); //last parameter is the name of this app
105 
106  std::string ss = exec(syscom);
107  std::stringstream sss(ss);
108  std::string sfunc;
109  std::string sloc;
110  std::getline(sss,sfunc,'\n');
111  std::getline(sss,sloc,'\n');
112  str << std::endl;
113  str << "\033[35m" << "Function:" << std::endl << sfunc << "\033[0m" << std::endl;
114  str << "\033[1;31m" << "Location:" << std::endl << sloc << "\033[0m" << std::endl;
115  }
116  else
117  {
118  str << std::endl;
119  }
120  }
121 
122  std::cerr << str.str() << std::endl;
123 
124 #else
125 
126  std::cerr << "Stack trace deactivated" << std::endl;
127 
128 #endif
129 }
130 
131 
132 
133 #endif /* OPENFPM_DATA_SRC_UTIL_PRINT_STACK_HPP_ */