运行异常监控
只有非windows才启作用.linux异常监控
1 #ifndef ABTOR_WINDOWS 2 initLinuxDump(logdir.c_str()); 3 #endif
1 #pragma once 2 3 #ifndef ABTOR_WINDOWS 4 5 #include<stdio.h> 6 #include<string.h> 7 #include<stdlib.h> 8 #include <signal.h> 9 #include <execinfo.h> 10 11 #include<sys/types.h> 12 #include<unistd.h> 13 #include<fcntl.h> 14 15 #include <pthread.h> 16 #include <sys/types.h> 17 #include <sys/syscall.h> 18 #include <string.h> 19 20 static int _core_dump_signals[] = { 21 /*SIGABRT,*/SIGFPE, SIGILL, SIGQUIT, SIGSEGV, 22 SIGTRAP, SIGSYS, SIGBUS, SIGXCPU, SIGXFSZ 23 #ifdef SIGEMT 24 ,SIGEMT 25 #endif 26 }; 27 28 static char g_log_dir[1024] = {0}; 29 30 31 32 struct flock* file_lock(short type, short whence) 33 { 34 static struct flock ret ; 35 ret.l_type = type ; 36 ret.l_start = 0 ; 37 ret.l_whence = whence ; 38 ret.l_len = 0 ; 39 ret.l_pid = getpid() ; 40 return &ret ; 41 } 42 43 void saveBackTrace(int signalno) 44 { 45 46 char logFile[1024] = {0}; 47 FILE* fLog = NULL; 48 sprintf(logFile,"%s/core.dump",g_log_dir); 49 fLog = fopen(logFile,"w+"); 50 if(fLog == NULL) 51 { 52 return; 53 } 54 int fd = fileno(fLog); 55 fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET)); 56 57 char buffer[4096] = {0}; 58 int count = readlink("/proc/self/exe", buffer, 4096); 59 if(count > 0) 60 { 61 buffer[count] = '\n'; 62 buffer[count + 1] = 0; 63 fwrite(buffer, 1, count + 1, fLog); 64 fflush(fLog); 65 } 66 67 68 //#记录捕捉到的信号 69 strcpy(buffer, "Catch signal: "); 70 printf("Catch signal:%d\n",signalno); 71 fflush(stdout); 72 switch (signalno) 73 { 74 case SIGSEGV: strcat(buffer, "SIGSEGV\n"); 75 break; 76 case SIGILL: strcat(buffer, "SIGILL\n"); 77 break; 78 case SIGFPE: strcat(buffer, "SIGFPE\n"); 79 break; 80 case SIGABRT: strcat(buffer, "SIGABRT\n"); 81 break; 82 case SIGTERM: strcat(buffer, "SIGTERM\n"); 83 break; 84 case SIGKILL: strcat(buffer, "SIGKILL\n"); 85 break; 86 case SIGXFSZ: strcat(buffer, "SIGXFSZ\n"); 87 88 break; 89 default: sprintf(buffer, "Catch signal: %d\n", signalno); 90 break; 91 } 92 fwrite(buffer, 1, strlen(buffer), fLog); 93 fflush(fLog); 94 95 //#打印一些全局变量。去掉这个信息的打印,因为每个crash的thread id号都不一样,不方便判断crash是否一样。 96 printf("thread lwpid: %u\n", syscall(SYS_gettid)); 97 // sprintf(buffer, "thread lwpid: %u\n", syscall(SYS_gettid)); 98 // fwrite(buffer, 1, strlen(buffer), fLog); 99 // fflush(fLog); 100 // sprintf(buffer, "thread tid: %u\n", pthread_self()); 101 printf("thread tid: %u\n", pthread_self()); 102 // fwrite(buffer, 1, strlen(buffer), fLog); 103 // fflush(fLog); 104 105 printf("1\n"); 106 fflush(stdout); 107 //#打印堆栈信息 108 void* DumpArray[256]; 109 int nSize = backtrace(DumpArray, 256); 110 char** symbols = backtrace_symbols(DumpArray, nSize); 111 printf("DumpArraySize:%d symbols:%p\n",nSize,symbols); 112 if (symbols) 113 { 114 if (nSize > 256) 115 { 116 nSize = 256; 117 } 118 if (nSize > 0) 119 { 120 #if 0 121 //定位源代码行 122 char cmd[264] = "addr2line -f -e "; 123 char buff1[256] = { 0 }, buff2[1024] = { 0 }, buff3[256] = { 0 }; 124 char* prog = cmd + 16; 125 readlink("/proc/self/exe", prog, sizeof(cmd) - (prog-cmd)-1);// 获取进程的完整路径 126 int leftlen = strlen(cmd); 127 prog = cmd + leftlen; 128 leftlen = 263 - leftlen; 129 for (size_t i = 0; i < nSize; ++i) 130 { 131 snprintf(prog, leftlen, " %p\n", DumpArray[i]); 132 133 FILE* fp = popen(cmd, "r"); 134 if (fp != NULL) 135 { 136 if (NULL != fgets(buff1, 255, fp)) 137 { 138 // fgets(buff2, 1023, fp); 139 // if (buff2[strlen(buff2) - 1] == '\n') 140 // buff2[strlen(buff2) - 1] = 0; 141 if(buff1[0] == '\?') 142 { 143 fprintf(fLog, "%s\n", symbols[i]+40); 144 printf("%s\n", symbols[i]+40); 145 } 146 else 147 { 148 snprintf(buff3, 255, "c++filt %s\n", buff1);//用c++filt 使函数名可视化 149 FILE* fp2 = popen(buff3, "r"); 150 if (fp2 && fgets(buff3, 255, fp2)) { 151 fprintf(fLog, "%s %s\n", prog, buff3); 152 printf("%s %s\n", prog, buff3); 153 fflush(fLog); 154 pclose(fp2); 155 } 156 else 157 { 158 fprintf(fLog, "%s %s\n", prog, buff1); 159 printf("%s %s\n", prog, buff1); 160 fflush(fLog); 161 } 162 } 163 164 165 } 166 pclose(fp); 167 } 168 } 169 #else 170 for (int i = 0; i < nSize; i++) 171 { 172 fwrite(symbols[i], 1, strlen(symbols[i]), fLog); 173 fwrite("\n", 1, 1, fLog); 174 fflush(fLog); 175 printf("%s\n",symbols[i]); 176 fflush(stdout); 177 } 178 #endif 179 } 180 free(symbols); 181 } 182 fcntl(fd, F_SETLK, file_lock(F_UNLCK, SEEK_SET)); 183 fclose(fLog); 184 printf("2\n"); 185 fflush(stdout); 186 187 signal(signalno, SIG_DFL); 188 raise(signalno); 189 exit(3); 190 } 191 192 193 void initLinuxDump(const char* logPath) 194 { 195 //设置 信好的处理函数 196 strcpy(g_log_dir, logPath); 197 198 signal(SIGSEGV, saveBackTrace); 199 for (int i = 0; i < (sizeof(_core_dump_signals) / sizeof((_core_dump_signals)[0])); i++) 200 { 201 signal(_core_dump_signals[i], saveBackTrace); 202 } 203 204 // block SIGINT to all child process: 205 //sigset_t bset, oset; 206 //sigemptyset(&bset); 207 //sigaddset(&bset, SIGINT); 208 // equivalent to sigprocmask 209 //设置信号为阻塞信号 210 //if (pthread_sigmask(SIG_BLOCK, &bset, &oset) != 0) 211 { 212 // printf("set thread signal mask error!"); 213 } 214 215 } 216 217 218 #endif