ivbacktrace.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include "ivbacktrace.h"
  2. #ifndef USE_BOOSTBACKTRACE
  3. #ifdef Q_OS_WIN32
  4. void RegisterIVBackTrace()
  5. {
  6. }
  7. #else
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <string.h>
  13. #include <signal.h>
  14. #include <execinfo.h>
  15. #include <QDateTime>
  16. #include <QDir>
  17. void out_stack(char *sig);
  18. void signal_exit(int dunno)
  19. {
  20. char* signal_str = (char*)" ";
  21. char dunno_str[10] = {0};
  22. sprintf(dunno_str, "%d", dunno);
  23. switch (dunno)
  24. {
  25. case 1:
  26. signal_str = (char*)"SIGHUP(1)";
  27. break;
  28. case 2:
  29. signal_str = (char*)"SIGINT(2:CTRL_C)"; //CTRL_C
  30. break;
  31. case 3:
  32. signal_str = (char*)"SIGQUIT(3)";
  33. break;
  34. case 6:
  35. {
  36. signal_str = (char*)"SIGABRT(6)";
  37. out_stack(signal_str);
  38. }
  39. break;
  40. case 9:
  41. signal_str = (char*)"SIGKILL(9)";
  42. break;
  43. case 15:
  44. signal_str = (char*)"SIGTERM(15 KILL)"; //kill
  45. break;
  46. case 11:
  47. {
  48. signal_str = (char*)"SIGSEGV(11)"; //SIGSEGV
  49. out_stack(signal_str);
  50. }
  51. break;
  52. default:
  53. signal_str = (char*)"OTHER";
  54. break;
  55. }
  56. exit(0);
  57. }
  58. size_t get_executable_path( char* processdir,char* processname, size_t len)
  59. {
  60. char* path_end;
  61. int nsize;
  62. if((nsize =readlink("/proc/self/exe", processdir,len)) <=0)
  63. return -1;
  64. processdir[nsize] = '\0';
  65. path_end = strrchr(processdir, '/');
  66. if(path_end == NULL)
  67. return -1;
  68. ++path_end;
  69. strcpy(processname, path_end);
  70. *path_end = '\0';
  71. return (size_t)(path_end - processdir);
  72. }
  73. void savetofile(char * stroutput)
  74. {
  75. qDebug("save file");
  76. char strpath[1024];
  77. QDateTime dt = QDateTime::currentDateTime();
  78. char path[1000];
  79. char processname[1024];
  80. get_executable_path(path, processname, 1000);
  81. snprintf(strpath,255,"%s/log/%s-%d-%s.log",getenv("HOME"),processname, getpid(),dt.toString("yyyyMMddhhmmsszzz").toLatin1().data());
  82. char strdir[1024];
  83. snprintf(strdir,255,"%s/log",getenv("HOME"));
  84. QDir xdir;
  85. xdir.setPath(strdir);
  86. if(!xdir.exists())
  87. {
  88. qDebug("create dir %s",strdir);
  89. xdir.mkdir(strdir);
  90. }
  91. qDebug("%s\n",strpath);
  92. FILE* file = fopen(strpath,"w+");
  93. if(file != nullptr)
  94. {
  95. fwrite(stroutput,strnlen(stroutput,6000),1,file);
  96. }
  97. fclose(file);
  98. }
  99. static void output_addrline(char addr[],char * strtem)
  100. {
  101. char cmd[256];
  102. char line[256];
  103. char addrline[32]={0,};
  104. char *str1, *str2;
  105. FILE* file;
  106. snprintf(strtem,1000," ");
  107. // str1 = strchr(addr,'[');
  108. // str2 = strchr(addr, ']');
  109. str1 = strchr(addr,'(');
  110. str2 = strchr(addr, ')');
  111. if(str1 == NULL || str2 == NULL)
  112. {
  113. return;
  114. }
  115. if((str2 -str1 -2)<=0)
  116. {
  117. // printf("can't find address,please use -g compile.");
  118. // strncpy(strtem,"can't find address,please use -g compile.",256);
  119. str1 = strchr(addr,'[');
  120. str2 = strchr(addr, ']');
  121. if(str1 == NULL || str2 == NULL)
  122. {
  123. return;
  124. }
  125. if((str2 -str1 -2)<=0)
  126. {
  127. printf("can't find address,please use -g compile.");
  128. strncpy(strtem,"can't find address,please use -g compile.",256);
  129. return;
  130. }
  131. }
  132. memcpy(addrline, str1 + 1, str2 -str1 -1);
  133. snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %s ", getpid(), addrline);
  134. qDebug("%s\n",cmd);
  135. file = popen(cmd, "r");
  136. if(NULL != fgets(line, 256, file))
  137. {
  138. printf("%s\n", line);
  139. snprintf(strtem,1000,"%s\n",line);
  140. }
  141. if(strnlen(line,255) == 0)
  142. {
  143. printf("no addr.\n");
  144. }
  145. pclose(file);
  146. }
  147. static void proc_addrline(int64_t xaddr,char * strtem)
  148. {
  149. char cmd[256];
  150. char line[256];
  151. FILE* file;
  152. snprintf(strtem,1000," ");
  153. snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %x ", getpid(), xaddr);
  154. qDebug("%s\n",cmd);
  155. file = popen(cmd, "r");
  156. if(NULL != fgets(line, 256, file))
  157. {
  158. printf("%s\n", line);
  159. snprintf(strtem,1000,"%s\n",line);
  160. }
  161. if(strnlen(line,255) == 0)
  162. {
  163. printf("no addr.\n");
  164. }
  165. pclose(file);
  166. }
  167. void out_stack(char *sig)
  168. {
  169. void *array[32];
  170. size_t size;
  171. char **strings;
  172. size_t i;
  173. char stroutput[6000];
  174. char strtem[1000];
  175. snprintf(stroutput,3000," ");
  176. printf("%s\n", sig);
  177. qDebug("%s\n", sig);
  178. size = backtrace (array, 32);
  179. //该函数用于获取当前线程的调用堆栈,获取的信息将会被存放在array中,
  180. //它是一个指针列表。参数 32 用来指定array中可以保存多少个void* 元素。
  181. //函数返回值是实际获取的指针个数,最大不超过32大小.
  182. strings = backtrace_symbols (array, size);
  183. /* backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组.
  184. * 参数array应该是从backtrace函数获取的指针数组,
  185. * size是该数组中的元素个数(backtrace的返回值)
  186. * 函数返回值是一个指向字符串数组的指针,它的大小同array相同.
  187. * 每个字符串包含了一个相对于array中对应元素的可打印信息.
  188. * 它包括函数名,函数的偏移地址,和实际的返回地址
  189. */
  190. if (NULL == strings)
  191. {
  192. printf("backtrace_symbols\n");
  193. return ;
  194. }
  195. qDebug("size is %d",(int)size);
  196. for (i = 0; i <size; i++)
  197. {
  198. // qDebug("i is %d",i);
  199. printf("%s\n",strings[i]);
  200. // snprintf(strtem,1000,"%s\n",strings[i]);
  201. // strncat(stroutput,strtem,6000);
  202. // output_addrline(strings[i],strtem);
  203. // strncat(stroutput,strtem,6000);
  204. }
  205. for(i=0;i<size;i++)
  206. {
  207. int64_t xaddr = (int64_t)((int *)array[i]);
  208. printf("addr is %x\n", xaddr);
  209. snprintf(strtem,1000,"addr is %x\n", xaddr);
  210. strncat(stroutput,strtem,6000);
  211. proc_addrline(xaddr,strtem);
  212. strncat(stroutput,strtem,6000);
  213. }
  214. free(strings);
  215. savetofile(stroutput);
  216. QTime x;
  217. x.start();
  218. while((unsigned int)(x.elapsed())<100)
  219. {
  220. // qDebug("hello");
  221. }
  222. }
  223. void RegisterIVBackTrace()
  224. {
  225. signal(SIGHUP, signal_exit);
  226. signal(SIGINT, signal_exit);
  227. signal(SIGQUIT, signal_exit);
  228. signal(SIGABRT, signal_exit);
  229. signal(SIGKILL, signal_exit);
  230. signal(SIGTERM, signal_exit);
  231. signal(SIGSEGV, signal_exit);
  232. }
  233. #endif
  234. #endif
  235. #if 0
  236. //C语言标准定义了6个信号。都定义在signal.h头文件中。
  237. //SIGABRT - 异常中止。
  238. //SIGFPE - 浮点异常。
  239. //SIGILL - 无效指令。
  240. //SIGINT - 交互的用户按键请求,默认情况下,这会导致进程终止。
  241. //SIGSEGV - 无效内存访问。
  242. //SIGTERM - 程序的中止请求。
  243. /* ISO C99 signals. */
  244. #define SIGINT 2 /* Interactive attention signal. */
  245. #define SIGILL 4 /* Illegal instruction. */
  246. #define SIGABRT 6 /* Abnormal termination. */
  247. #define SIGFPE 8 /* Erroneous arithmetic operation. */
  248. #define SIGSEGV 11 /* Invalid access to storage. */
  249. #define SIGTERM 15 /* Termination request. */
  250. /* Historical signals specified by POSIX. */
  251. #define SIGHUP 1 /* Hangup. */
  252. #define SIGQUIT 3 /* Quit. */
  253. #define SIGTRAP 5 /* Trace/breakpoint trap. */
  254. #define SIGKILL 9 /* Killed. */
  255. #define SIGBUS 10 /* Bus error. */
  256. #define SIGSYS 12 /* Bad system call. */
  257. #define SIGPIPE 13 /* Broken pipe. */
  258. #define SIGALRM 14 /* Alarm clock. */
  259. #endif