收集错误报告

程序总是难以避免地会出现各种问题,严重时甚至崩溃退出。现在很多应用程序在出现崩溃时会收集相关错误信息,发送错误报告,方便开发人员定位并修复问题。

最近在实际工作中也遇到了类似的问题,客户端通过PLSQL等工具连接到远程数据库服务器做运维操作,出于安全性的考虑,这里客户端并不是直接连到服务器,而是先连到类似于跳板机的设备,再由跳板机连接真实的服务器,数据流向如下图所示。

现在需要在跳板机处将客户端输入的命令,即待执行的SQL语句提取出来。对通信过程抓包会发现,通信数据并非明文,但有一定的规律可循,由于oracle公司并未公开数据格式、不同版本的数据格式可能有差异等原因,想完全准确无误地从通信数据包中提取SQL语句并非易事,目前采用的做法是凭经验猜测解析。

事实证明,这个办法在大部分情况下能很好地工作,只有在极少数情况下,由于输入数据的某些特征以及解析过程没有做好保护措施,会出现内存越界读写问题,导致整个程序崩溃。可见,目前所掌握的经验还不足以百分之百覆盖所有的情况。

有一个办法可以不让程序异常退出,同时把会导致程序崩溃的数据收集起来,具体做法是在接收到输入数据后,生成子进程,由子进程负责解析,父进程等待结果。如果子进程正常退出,说明解析成功,无需额外处理;反之如果子进程异常退出,说明解析过程出了问题,这时父进程把输入数据记到磁盘文件中,供开发人员分析,以完善SQL语句解析经验。

以下给个例子,对上面的思路做简单说明。程序功能是输入一个字符串,如果字符串长度为奇数,则异常退出。

 1 #include <stdio.h>
 2 #include <string.h>
 3 int main()
 4 {
 5     char buf[64];
 6     for (;;) {
 7         scanf("%[^\n]%*c", buf);
 8         if (strlen(buf) & 1)
 9             memset(0, 0, 1); 
10     }   
11     return 0;
12 }
View Code

 以下是改进做法。

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <unistd.h>
 4 #include <stdlib.h>
 5 #include <string.h>
 6 #include <wait.h>
 7 #include <sys/stat.h>
 8 #include <fcntl.h>
 9 void SaveErr(const char *buf)
10 {
11     FILE *fp = fopen("err.log", "a+");
12     fprintf(fp, "%s\n", buf);
13     fclose(fp);
14 }
15 int main()
16 {
17     int fd[2], status;
18     pid_t pid;
19     char buf[64], tmp[64];
20 
21     for (;;) {
22         scanf("%[^\n]%*c", buf);
23         pipe(fd);
24         pid = fork();
25         if (pid > 0) {
26             close(fd[0]);
27             write(fd[1], buf, strlen(buf));
28             waitpid(pid, &status, 0);
29             if (!WIFEXITED(status))
30                 SaveErr(buf);
31         } else if (0 == pid) {
32             close(fd[1]);
33             read(fd[0], tmp, sizeof(tmp));
34             if (strlen(tmp) & 1)
35                 memset(0, 0, 1);
36             return 0;
37         }
38     }
39     return 0;
40 }
View Code

 

posted @ 2015-07-02 17:30  boyfaceone  阅读(339)  评论(0编辑  收藏  举报