123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- #include "ivbacktrace.h"
- #ifndef USE_BOOSTBACKTRACE
- #ifdef Q_OS_WIN32
- void RegisterIVBackTrace()
- {
- }
- #else
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <signal.h>
- #include <execinfo.h>
- #include <QDateTime>
- #include <QDir>
- void out_stack(char *sig);
- void signal_exit(int dunno)
- {
- char* signal_str = (char*)" ";
- char dunno_str[10] = {0};
- sprintf(dunno_str, "%d", dunno);
- switch (dunno)
- {
- case 1:
- signal_str = (char*)"SIGHUP(1)";
- break;
- case 2:
- signal_str = (char*)"SIGINT(2:CTRL_C)"; //CTRL_C
- break;
- case 3:
- signal_str = (char*)"SIGQUIT(3)";
- break;
- case 6:
- {
- signal_str = (char*)"SIGABRT(6)";
- out_stack(signal_str);
- }
- break;
- case 9:
- signal_str = (char*)"SIGKILL(9)";
- break;
- case 15:
- signal_str = (char*)"SIGTERM(15 KILL)"; //kill
- break;
- case 11:
- {
- signal_str = (char*)"SIGSEGV(11)"; //SIGSEGV
- out_stack(signal_str);
- }
- break;
- default:
- signal_str = (char*)"OTHER";
- break;
- }
- exit(0);
- }
- size_t get_executable_path( char* processdir,char* processname, size_t len)
- {
- char* path_end;
- int nsize;
- if((nsize =readlink("/proc/self/exe", processdir,len)) <=0)
- return -1;
- processdir[nsize] = '\0';
- path_end = strrchr(processdir, '/');
- if(path_end == NULL)
- return -1;
- ++path_end;
- strcpy(processname, path_end);
- *path_end = '\0';
- return (size_t)(path_end - processdir);
- }
- void savetofile(char * stroutput)
- {
- qDebug("save file");
- char strpath[1024];
- QDateTime dt = QDateTime::currentDateTime();
- char path[1000];
- char processname[1024];
- get_executable_path(path, processname, 1000);
- snprintf(strpath,255,"%s/log/%s-%d-%s.log",getenv("HOME"),processname, getpid(),dt.toString("yyyyMMddhhmmsszzz").toLatin1().data());
- char strdir[1024];
- snprintf(strdir,255,"%s/log",getenv("HOME"));
- QDir xdir;
- xdir.setPath(strdir);
- if(!xdir.exists())
- {
- qDebug("create dir %s",strdir);
- xdir.mkdir(strdir);
- }
- qDebug("%s\n",strpath);
- FILE* file = fopen(strpath,"w+");
- if(file != nullptr)
- {
- fwrite(stroutput,strnlen(stroutput,6000),1,file);
- }
- fclose(file);
- }
- static void output_addrline(char addr[],char * strtem)
- {
- char cmd[256];
- char line[256];
- char addrline[32]={0,};
- char *str1, *str2;
- FILE* file;
- snprintf(strtem,1000," ");
- // str1 = strchr(addr,'[');
- // str2 = strchr(addr, ']');
- str1 = strchr(addr,'(');
- str2 = strchr(addr, ')');
- if(str1 == NULL || str2 == NULL)
- {
- return;
- }
- if((str2 -str1 -2)<=0)
- {
- // printf("can't find address,please use -g compile.");
- // strncpy(strtem,"can't find address,please use -g compile.",256);
- str1 = strchr(addr,'[');
- str2 = strchr(addr, ']');
- if(str1 == NULL || str2 == NULL)
- {
- return;
- }
- if((str2 -str1 -2)<=0)
- {
- printf("can't find address,please use -g compile.");
- strncpy(strtem,"can't find address,please use -g compile.",256);
- return;
- }
- }
- memcpy(addrline, str1 + 1, str2 -str1 -1);
- snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %s ", getpid(), addrline);
- qDebug("%s\n",cmd);
- file = popen(cmd, "r");
- if(NULL != fgets(line, 256, file))
- {
- printf("%s\n", line);
- snprintf(strtem,1000,"%s\n",line);
- }
- if(strnlen(line,255) == 0)
- {
- printf("no addr.\n");
- }
- pclose(file);
- }
- static void proc_addrline(int64_t xaddr,char * strtem)
- {
- char cmd[256];
- char line[256];
- FILE* file;
- snprintf(strtem,1000," ");
- snprintf(cmd, sizeof(cmd), "addr2line -e /proc/%d/exe %x ", getpid(), xaddr);
- qDebug("%s\n",cmd);
- file = popen(cmd, "r");
- if(NULL != fgets(line, 256, file))
- {
- printf("%s\n", line);
- snprintf(strtem,1000,"%s\n",line);
- }
- if(strnlen(line,255) == 0)
- {
- printf("no addr.\n");
- }
- pclose(file);
- }
- void out_stack(char *sig)
- {
- void *array[32];
- size_t size;
- char **strings;
- size_t i;
- char stroutput[6000];
- char strtem[1000];
- snprintf(stroutput,3000," ");
- printf("%s\n", sig);
- qDebug("%s\n", sig);
- size = backtrace (array, 32);
- //该函数用于获取当前线程的调用堆栈,获取的信息将会被存放在array中,
- //它是一个指针列表。参数 32 用来指定array中可以保存多少个void* 元素。
- //函数返回值是实际获取的指针个数,最大不超过32大小.
- strings = backtrace_symbols (array, size);
- /* backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组.
- * 参数array应该是从backtrace函数获取的指针数组,
- * size是该数组中的元素个数(backtrace的返回值)
- * 函数返回值是一个指向字符串数组的指针,它的大小同array相同.
- * 每个字符串包含了一个相对于array中对应元素的可打印信息.
- * 它包括函数名,函数的偏移地址,和实际的返回地址
- */
- if (NULL == strings)
- {
- printf("backtrace_symbols\n");
- return ;
- }
- qDebug("size is %d",(int)size);
- for (i = 0; i <size; i++)
- {
- // qDebug("i is %d",i);
- printf("%s\n",strings[i]);
- // snprintf(strtem,1000,"%s\n",strings[i]);
- // strncat(stroutput,strtem,6000);
- // output_addrline(strings[i],strtem);
- // strncat(stroutput,strtem,6000);
- }
- for(i=0;i<size;i++)
- {
- int64_t xaddr = (int64_t)((int *)array[i]);
- printf("addr is %x\n", xaddr);
- snprintf(strtem,1000,"addr is %x\n", xaddr);
- strncat(stroutput,strtem,6000);
- proc_addrline(xaddr,strtem);
- strncat(stroutput,strtem,6000);
- }
- free(strings);
- savetofile(stroutput);
- QTime x;
- x.start();
- while((unsigned int)(x.elapsed())<100)
- {
- // qDebug("hello");
- }
- }
- void RegisterIVBackTrace()
- {
- signal(SIGHUP, signal_exit);
- signal(SIGINT, signal_exit);
- signal(SIGQUIT, signal_exit);
- signal(SIGABRT, signal_exit);
- signal(SIGKILL, signal_exit);
- signal(SIGTERM, signal_exit);
- signal(SIGSEGV, signal_exit);
- }
- #endif
- #endif
- #if 0
- //C语言标准定义了6个信号。都定义在signal.h头文件中。
- //SIGABRT - 异常中止。
- //SIGFPE - 浮点异常。
- //SIGILL - 无效指令。
- //SIGINT - 交互的用户按键请求,默认情况下,这会导致进程终止。
- //SIGSEGV - 无效内存访问。
- //SIGTERM - 程序的中止请求。
- /* ISO C99 signals. */
- #define SIGINT 2 /* Interactive attention signal. */
- #define SIGILL 4 /* Illegal instruction. */
- #define SIGABRT 6 /* Abnormal termination. */
- #define SIGFPE 8 /* Erroneous arithmetic operation. */
- #define SIGSEGV 11 /* Invalid access to storage. */
- #define SIGTERM 15 /* Termination request. */
- /* Historical signals specified by POSIX. */
- #define SIGHUP 1 /* Hangup. */
- #define SIGQUIT 3 /* Quit. */
- #define SIGTRAP 5 /* Trace/breakpoint trap. */
- #define SIGKILL 9 /* Killed. */
- #define SIGBUS 10 /* Bus error. */
- #define SIGSYS 12 /* Bad system call. */
- #define SIGPIPE 13 /* Broken pipe. */
- #define SIGALRM 14 /* Alarm clock. */
- #endif
|