stacktrace.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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 _STACKTRACE_H_
  8. #define _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. int frame=0;
  23. for(int i = skip; i < addrlen; i++) {
  24. // Get command
  25. char cmd[10240];
  26. sprintf(cmd, "addr2line -f -C -i -e %s %016p", fname, addrlist[i]);
  27. // Execute command
  28. FILE* pipe = popen(cmd, "r");
  29. if (!pipe) continue;
  30. char buffer0[10240];
  31. char buffer1[10240];
  32. fgets(buffer0, sizeof(buffer0)-1, pipe);
  33. fgets(buffer1, sizeof(buffer1)-1, pipe);
  34. for(size_t j=0;j<sizeof(buffer0)-1;j++){if(buffer0[j]=='\n') buffer0[j]=' ';}
  35. for(size_t j=0;j<sizeof(buffer1)-1;j++){if(buffer1[j]=='\n') buffer1[j]=' ';}
  36. pclose(pipe);
  37. // Print output
  38. if(buffer0[0]!='?'){
  39. fprintf(out, "[%d] %s: %s\n", i-skip, buffer1, buffer0);
  40. }else{
  41. fprintf(out, "[%d] %016p: %s\n", i-skip, addrlist[i], symbollist[i]);
  42. }
  43. }
  44. fprintf( stderr, "\n");
  45. }
  46. inline void abortHandler( int signum, siginfo_t* si, void* unused ){
  47. static bool first_time=true;
  48. #pragma omp critical (STACK_TRACE)
  49. if(first_time){
  50. first_time=false;
  51. char* name = NULL;
  52. switch( signum ){
  53. case SIGABRT: name = "SIGABRT"; break;
  54. case SIGSEGV: name = "SIGSEGV"; break;
  55. case SIGBUS: name = "SIGBUS"; break;
  56. case SIGILL: name = "SIGILL"; break;
  57. case SIGFPE: name = "SIGFPE"; break;
  58. }
  59. if( name ) fprintf( stderr, "\nCaught signal %d (%s)\n", signum, name );
  60. else fprintf( stderr, "\nCaught signal %d\n", signum );
  61. print_stacktrace(stderr,2);
  62. }
  63. exit( signum );
  64. }
  65. inline int SetSigHandler(){
  66. struct sigaction sa;
  67. sa.sa_flags = SA_RESTART | SA_SIGINFO;
  68. sa.sa_sigaction = abortHandler;
  69. sigemptyset (&sa.sa_mask);
  70. sigaction( SIGABRT, &sa, NULL );
  71. sigaction( SIGSEGV, &sa, NULL );
  72. sigaction( SIGBUS, &sa, NULL );
  73. sigaction( SIGILL, &sa, NULL );
  74. sigaction( SIGFPE, &sa, NULL );
  75. sigaction( SIGPIPE, &sa, NULL );
  76. return -1;
  77. }
  78. const int sig_handler=SetSigHandler();
  79. }//end namespace
  80. #endif // _STACKTRACE_H_