HTML5技术

记录一次线上组件崩溃的解决过程 - HarlanC

字号+ 作者:H5之家 来源:H5之家 2017-06-22 10:01 我要评论( )

记录一次线上组件崩溃的解决过程 马上就要离职了,想想工作中有些东西还是需要沉淀下来的,不仅仅要沉淀到心里,因为年纪大了^_^,很容易忘记,不是有句话么,好记性不如烂笔头。 分析这个bug之前先说点别的。 解决bug的大致思路 我觉的解bug和医生看病是一

记录一次线上组件崩溃的解决过程


马上就要离职了,想想工作中有些东西还是需要沉淀下来的,不仅仅要沉淀到心里,因为年纪大了^_^,很容易忘记,不是有句话么,好记性不如烂笔头。

分析这个bug之前先说点别的。

解决bug的大致思路

我觉的解bug和医生看病是一样的,中医看病讲究望闻问切。软件出了毛病也按这个套路来,但是不需要闻。

我们开发的产品运行在windows server 平台上,几个月之前fix过一个线上发现的bug。对于有经验的开发人员来说,需要解决的bug分为两种:能稳定重现的和不能稳定重现的。只要能够稳定重现,从客户提供的种种数据中总能顺藤摸瓜,找到问题根源。在我们的软件中,这些数据包括以下几种:

  • Windows Event Log,这也分为两个不同的级别(只说和我们相关的)
  • windows logs,这是操作系统级别的log,若遇到组件崩溃,windows logs下面的Application会打印log记录。
  • Application and Services Logs,我们的产品自定义的log放在这个目录下面,这些log这是最直接的信息,如插在软件中的一个个索引,报错之后能够很快定位代码位置,找到问题突破口。
  • 根据bug的难易程度,找问题出现的根源有三种手段,可以层层递进或者同时进行:

    还有一种特殊情况就是出现组件崩溃时,这种情况下我们会抓取到dump文件,把dump文件导入到visual studio中,就能一步步查看call stack来寻找问题的出错点。

    好了,前面将我们解决bug时需要的信息以及解决方法做了一个简单的总结,下面就具体说一下博主一次解决组件崩溃的经历。很早之前的事了,dump文件和环境都没有了,主要从以下三点介绍:

    问题描述

    客户发现有一个server组件一周会出现至少一次崩溃,windows的application log报出类似如下错误:

    根据客户的描述,这个server组件大约有100多个socket连接,这些连接每隔几分钟就会有一些断掉然后重连(有可能是网络问题导致的),他们推断这和组件崩溃有一定的关系。

    因为问题不好重现,测试团队先行重现客户的这个bug。使用客户数据库,实现脚本模拟客户的socket断开和重连。

    前面也说过,bug分为容易重新和不容易重现的,这个bug的第一个难点是如何重现,测试为了增加压力,将连接数增加至300,socket的断开时间间隔逐渐改小等等。

    如何抓取dump文件

    在重现问题之前,需要配置windows在组件崩溃时自动抓取dump文件,如何配置,很简单,将下面的注册表项导入注册表即可,注意要把DumpComponentName.exe替换为你的需要抓dump的组件。

    Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps] "DumpType"=dword:00000002 "DumpFolder"=hex(2):43,00,3a,00,5c,00,43,00,72,00,61,00,73,00,68,00,44,00,75,\ 00,6d,00,70,00,00,00 "DumpCount"=dword:000000ff [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\DumpComponentName.exe] "DumpType"=dword:00000002 "DumpCount"=dword:000000ff "DumpFolder"=hex(2):43,00,3a,00,5c,00,43,00,72,00,61,00,73,00,68,00,44,00,75,\ 00,6d,00,70,00,5c,00,44,00,75,00,6d,00,70,00,43,00,6f,00,6d,00,70,00,6f,00,\ 6e,00,65,00,6e,00,74,00,4e,00,61,00,6d,00,65,00,00,00 问题根源分析

    因为dump文件和环境都不在了,不能介绍分析dump文件的过程了。只能分析最后的结果,发现了两个问题:

    问题一:有关STL容器的线程安全问题

    有关这个问题建议先拜读一下Scott Meyers的effective STL 条款12。

    引用其中的话:

    在STL容器(和大多数厂商的愿望)里对多线程支持的黄金规则已经由SGI定义,并且在它们的STL网站[21]上
    发布。大体上说,你能从实现里确定的最多是下列内容:

  • 多个读取者是安全的。多线程可能同时读取一个容器的内容,这将正确地执行。当然,在读取时不能
    有任何写入者操作这个容器。
  • 对不同容器的多个写入者是安全的。多线程可以同时写不同的容器。
  • 也就是STL容器只能够在两种情况下保证多线程安全:

  • 同时读取一个不会发生变化的容器。
  • 同时写多个不同的容器。
  • 仅仅这两种情况,看看下面的发现有问题的code,你能看出问题在哪里么?

    template<typename T> ResourceResult getValue(ResourceKey key, T value) { ResourceResult result = ResourceFailure; resourcevalues_.guard();//lock Resources::iterator resource = resourcevalues_.resources().find(key); if (resource == resourcevalues_.resources().end()) // not found { resourcevalues_.addResource(key, resourceValueEntry); resourcevalues_.unGuard();//unlock } else { // item cached resourcevalues_.unGuard();//unlock if ((*resource).second.getValue(value)) { result = ResourceSuccess; } else { result = ResourceConversionError; } } return result; }

    这是典型的有问题的SLT多线程编程,写这段代码的coder可能是这么认为的:

  • 多线程不能同时写一个容器,因此加了lock
  • 多线程可以同时读一个容器。
  • 第一条没有问题,但是第二条是有前提的,同时读一个容器需要在容器不发生变化的情况下。如果恰巧在读取容器元素时另外一个线程对此容器进行写操作,读线程的iterator会失效,接下来的行为是未定义的。

    如何修改?对,读也需要加锁。

    template<typename T> ResourceResult getValue(ResourceKey key, T value) { ResourceResult result = ResourceFailure; resourcevalues_.guard();//lock Resources::iterator resource = resourcevalues_.resources().find(key); if (resource == resourcevalues_.resources().end()) // not found { resourcevalues_.addResource(key, resourceValueEntry); } else { // item cached if ((*resource).second.getValue(value)) { result = ResourceSuccess; } else { result = ResourceConversionError; } } resourcevalues_.unGuard();//unlock return result; }

    这就没有问题了。

    问题二 : 一个线程句柄释放问题 GeneratorThread::~GeneratorThread() { if (thread_) { stop(); thread_->wait(5000); delete thread_; } delete generator_; }

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 【线上问题】由防火墙导致的数据库空闲连接断开问题 - Trust_FreeDom

      【线上问题】由防火墙导致的数据库空闲连接断开问题 - Trust_FreeDom

      2017-06-15 16:00

    • localstorage和sessionstorage上手使用记录 - 蓓蕾心晴

      localstorage和sessionstorage上手使用记录 - 蓓蕾心晴

      2017-05-24 09:00

    • 学习HTML的第一次课 - 此人有病

      学习HTML的第一次课 - 此人有病

      2017-05-06 16:00

    • 如何快速处理线上故障 - 倒骑的驴

      如何快速处理线上故障 - 倒骑的驴

      2017-05-02 12:01

    网友点评