• 记解决Linux后台服务退出崩溃的问题


    问题描述

    在生产环境上,因为网络原因,导致初始化失败,在失败退出时有崩溃产生。

    问题分析

    在生产环境,linux环境的dump生成文件名为默认形式,实际dump文件名为core.4055的格式。通过原始elf文件来载入分析,发现调用栈入口都是具体的函数地址,而不是具体的函数名,生产环境上的这个dump,配合经过优化的elf文件,没有给解决这个问题提供有效帮助。下一个阶段,转入日志分析。

    由于后台服务有监控脚本,当进程崩溃时,会再重新拉起进程,每一个进程会生产对应的日志文件。从dump文件为core.4055上,可以得知崩溃进程的进程Id为4055,据此,在现有的众多日志文件中,通过

    grep pid *.log

    找出崩溃环境发生时涉及到的日志文件,一般找到多个日志文件,分别对应该服务内部各个模块的日志输出,然后再根据崩溃发生时间,通过

    ls --full-time core.4055

    查看精确到毫秒的崩溃时间,根据此时间,此处以 13:15:57 为说明,在前面的日志文件中,抽取该时间点之前的记录,进行日志聚合分析。

    grep -B 20 --no-filename "13:15:57" *.log | sort -k1 -o merge_core_4055.log
    -B:表示输出匹配行前20行的内容
    --no-filename:不输出多文件匹配时的文件名
    -k1:表示按日志中的时间排序

    通过上述指令,获得聚合文件后,然后再对照源码,逐行分析崩溃点前的日志打印,寻找蛛丝马迹。经过分析发现,怀疑是初始化失败触发的。至于为什么初始化失败,可以稍微探究下原因,不过在这个场景下,初始化失败是崩溃的触发点,而不是崩溃的产生点。

    问题复现:既然是初始化失败导致的,那么可以构造初始化失败场景,例如将连接地址设置无效,或者在调用完初始化后,始终返回初始化失败。通过这样的构造,可以稳定触发崩溃。最终发现,框架在初始化时,有一处单例服务的注入,在框架卸载时,会调用每个服务的UnInit后,再delete掉它。问题就出现在这里,delete一个单例指针,这个地址是由单例函数内部的静态局部变量提供的,释放不恰当的内存地址从而触发崩溃。

    解决方案以及小结

    此崩溃的问题原因是当程序退出时,释放了单例的局部静态变量地址,触发崩溃。修改方案有两个:

    • 是不用单例服务,而是用new的方式将服务注入框架。
    • 单例内部使用静态成员指针的形式来对外提供服务。

    在以后的开发实践中,可手动触发后台服务的正常退出,验证退出逻辑是否正常。
    在服务运行过程中,将自身进程Id以及线程Id输出是很有必要的,可以输出到日志文件,也可以单独输出到独立文件,例如mysql.pid文件。这样,方便后续在多种类型的日志文件中定位以及排错。

  • 相关阅读:
    数据结构——自学笔记一
    Xmind软件——xmind 8 pro下载激活推荐!!
    Java学习笔记之面向对象、static关键字
    解决“var/log/sysstat/sa21: 没有那个文件或目录 请检查是否允许数据收集”
    c++.net学习笔记
    Android Studio学习-连接真机测试教学
    Servlet总结二(文件路径)
    Servlet总结一
    多线程的使用
    Lock
  • 原文地址:https://www.cnblogs.com/cherishui/p/14015840.html
Copyright © 2020-2023  润新知