158static inline std::string
sh(
const std::string& cmd)
160 std::array<char, 128> buffer{};
162 std::shared_ptr<FILE> pipe(popen(cmd.c_str(),
"r"), pclose);
163 if(!pipe) {
throw std::runtime_error(
"popen() failed!"); }
164 while(feof(pipe.get()) == 0) {
165 if(fgets(buffer.data(), 128, pipe.get()) !=
nullptr) {
166 result += buffer.data();
175 std::ostringstream output;
176 output <<
"stack trace:" << std::endl;
179 void** addrlist =
new void*[maxFrames + 1];
182 int addrlen = backtrace(addrlist, maxFrames + 1);
185 output <<
" <empty, possibly corrupt>" << std::endl;
192 char** symbollist = backtrace_symbols(addrlist, addrlen);
195 size_t funcnamesize = 256;
196 auto* funcname =
new char[funcnamesize];
200 for(
int i = 2; i < addrlen; i++) {
201 char* begin_name =
nullptr;
202 char* begin_offset =
nullptr;
203 char* end_offset =
nullptr;
207 for(
char* p = symbollist[i]; *p != 0; ++p) {
210 }
else if(*p ==
'+') {
212 }
else if(*p ==
')' && begin_offset !=
nullptr) {
228 if(begin_name !=
nullptr && begin_offset !=
nullptr && end_offset !=
nullptr && begin_name < begin_offset) {
229 *begin_name++ =
'\0';
230 *begin_offset++ =
'\0';
238 char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
241 output <<
" " << symbollist[i] <<
": " << funcname <<
"+" << begin_offset << std::endl;
245 output <<
" " << symbollist[i] <<
": " << begin_name <<
"()+" << begin_offset << std::endl;
249 output <<
" " << symbollist[i] << std::endl;
264 std::array<char, 30> pid_buf{};
265 sprintf(pid_buf.data(),
"%d", getpid());
266 std::array<char, 512> name_buf{};
267 name_buf[readlink(
"/proc/self/exe", name_buf.data(), 511)] = 0;
268 prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
269 int child_pid = fork();
272 execl(
"/usr/bin/gdb",
"gdb",
"--batch",
"-n",
"-ex",
"thread",
"-ex",
"bt", name_buf.data(), pid_buf.data(),
nullptr);
275 waitpid(child_pid,
nullptr, 0);