stacktrace.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include <unistd.h>
  2. #include <signal.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <execinfo.h>
  6. #include <cxxabi.h>
  7. #ifndef _PVFMM_STACKTRACE_H_
  8. #define _PVFMM_STACKTRACE_H_
  9. namespace pvfmm{
  10. inline void print_stacktrace(FILE *out = stderr, int skip=1){
  11. // Get addresses
  12. void* addrlist[256];
  13. int addrlen = backtrace(addrlist, 255);
  14. for(int i=0;i<addrlen;i++) addrlist[i]=(char*)addrlist[i]-1;
  15. // Get symbols
  16. char** symbollist = backtrace_symbols(addrlist,addrlen);
  17. // Get filename
  18. char fname[10240];
  19. size_t fname_len = ::readlink("/proc/self/exe", fname, sizeof(fname)-1);
  20. fname[fname_len]='\0';
  21. // Print
  22. for(int i = skip; i < addrlen; i++) {
  23. // Get command
  24. char cmd[10240];
  25. sprintf(cmd, "addr2line -f -C -i -e %s %p", fname, addrlist[i]);
  26. // Execute command
  27. FILE* pipe = popen(cmd, "r");
  28. if (!pipe) continue;
  29. char buffer0[10240];
  30. char buffer1[10240];
  31. fgets(buffer0, sizeof(buffer0)-1, pipe);
  32. fgets(buffer1, sizeof(buffer1)-1, pipe);
  33. for(size_t j=0;j<sizeof(buffer0)-1;j++){if(buffer0[j]=='\n') buffer0[j]=' ';}
  34. for(size_t j=0;j<sizeof(buffer1)-1;j++){if(buffer1[j]=='\n') buffer1[j]=' ';}
  35. pclose(pipe);
  36. // Print output
  37. if(buffer0[0]!='?'){
  38. fprintf(out, "[%d] %s: %s\n", i-skip, buffer1, buffer0);
  39. }else{
  40. fprintf(out, "[%d] %p: %s\n", i-skip, addrlist[i], symbollist[i]);
  41. }
  42. }
  43. fprintf( stderr, "\n");
  44. }
  45. inline void abortHandler( int signum, siginfo_t* si, void* unused ){
  46. static bool first_time=true;
  47. UNUSED(unused);
  48. UNUSED(si);
  49. #pragma omp critical (STACK_TRACE)
  50. if(first_time){
  51. first_time=false;
  52. const char* name = NULL;
  53. switch( signum ){
  54. case SIGABRT: name = "SIGABRT"; break;
  55. case SIGSEGV: name = "SIGSEGV"; break;
  56. case SIGBUS: name = "SIGBUS"; break;
  57. case SIGILL: name = "SIGILL"; break;
  58. case SIGFPE: name = "SIGFPE"; break;
  59. }
  60. if( name ) fprintf( stderr, "\nCaught signal %d (%s)\n", signum, name );
  61. else fprintf( stderr, "\nCaught signal %d\n", signum );
  62. print_stacktrace(stderr,2);
  63. }
  64. exit( signum );
  65. }
  66. inline int SetSigHandler(){
  67. struct sigaction sa;
  68. sa.sa_flags = SA_RESTART | SA_SIGINFO;
  69. sa.sa_sigaction = abortHandler;
  70. sigemptyset (&sa.sa_mask);
  71. sigaction( SIGABRT, &sa, NULL );
  72. sigaction( SIGSEGV, &sa, NULL );
  73. sigaction( SIGBUS, &sa, NULL );
  74. sigaction( SIGILL, &sa, NULL );
  75. sigaction( SIGFPE, &sa, NULL );
  76. sigaction( SIGPIPE, &sa, NULL );
  77. return 0;
  78. }
  79. }//end namespace
  80. #endif // _PVFMM_STACKTRACE_H_