首页 > 分享 > 从对traffic_cop重启的一点修改学习GDB调试

从对traffic_cop重启的一点修改学习GDB调试

2013年7月15日     浏览数:2,331 发表评论 阅读评论

从对traffic_cop重启的一点修改学习GDB调试

开始之前先要祝贺一下,本文将要提到的问题已经在3天前被修复,即ts-1151,因此受到影响的版本还是比较多的,包括目前的稳定版3.2.4,本文也将从3.2.4来说明这个问题,因为问题已经修复,所以在这里就不说代码中的内容了,主要讲讲问题的发现过程——怎样使用GDB调试

首先说明下背景,启动ats之后会看到三个进程,分别是traffic_cop,traffic_manager和traffic_server。今天主要讲解的就是traffic_cop,traffic_cop的内容不多,主要起着监控并重启的作用,在源代码里面是独立的一部分,单独在cop目录下面。

    我们都知道traffic_server进程或者是traffic_manager进程死掉后会重新启动,继续服务,但是如果traffic_cop进程死掉之后呢,要说对整个ats的工作来说是没有影响的,但是如果前面两个进程再次死掉之后就没有办法再次重启了,因此之前和群主讨论过这个问题,说是创建一个crontab,这也是一个比较直接简单的办法了吧。但是发现杀掉traffic_cop去重启的时候会发生core dump,没办法重启起来,如下:
    cop1
    于是为了分析问题就需分析下core dump文件(redhat,centos默认不产生core dump,设置方法google,度娘都可以,不麻烦),现在切到ats的主目录就可以看到core文件了cop2
    使用gdb命令进行core dump文件的解析,这里可以使用两种命令方式打开core dump文件:
  • 1、gdb exec_file core_file

  • 2、gdb –c core_file exec_file

  • 3
    打开之后我们就可以看到栈里面的内容了,下面可以使用bt,where,up,down等命令来分析core文件
    cop5
    上面的bt命令的作用是查看函数堆栈(同where)up和down可以进行上下行的转换,还有其他的gdb命令大家可以自己去学习。
    通过栈的信息可以看到在TrafficCop.cc的1207行(由于gcc,g++在编译的时候有优化,略去了一些空行,注释等,所以行数可能不对应)的test_mgmt_cli_port()过后调用的就是系统库函数free(),然后调用的就是信号处理函数了,所以从test_mgmt_cli_port()函数入手,查询TrafficCop.cc的该函数可以看到:

    1191 static int
    1192 test_mgmt_cli_port()
    1193 {
    1194   TSString val;
    1195   int ret = 0;
    1196   if (TSRecordGetString("proxy.config.manager_binary", &val) !=  TS_ERR_OKAY) {
    1197     cop_log(COP_WARNING, "(cli test) unable to retrieve manager_binary\n");
    1198     ret = -1;
    1199   } else {
    1200     if (strcmp(val, manager_binary) != 0) {
    1201       cop_log(COP_WARNING, "(cli test) bad response value, got %s, expected %s\n", val, manager_binary);
    1202       ret = -1;
    1203     } 
    1204   } 
    1205   if (val){
    1206     TSfree(val);
    1207 }   
    1208   return ret;
    1209 }
    

    先查出问题的free(),可以看到这里有个TSfree(val),想想应该是重写了free()函数,可以用代码查看工具去看看,确实是的,这样子问题就能猜个大概了,free()出问题,一般是free()了不该free() 的东西,然后看free的是val,然后向上寻找val的相关信息。
    从定义的时候说起,这里首先是定义了一个空串,但是注意在这里只是定义了一个空串,并没有分配内存空间,所以这就会有一个隐患,当然了如果处理的好也是没有关系的,我们继续往下看,看看继续做了什么,首先是TSRecordGetString()取得manager_binary这个参数的值,然后在这里是可以对val进行内存空间分配的,但是假如这里没有对val分配的话,那后面的Free()就会有问题,在这里就不详细去追究后面的代码了,可以继续追寻的,会发现后面的分配内存的语句不一定会被执行,问题就定位了。当然了,解决问题的办法最简单就是开始的时候就让Val = NULL,这样子就不会出现上面的问题了。

分类: 分享 标签:
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.