当前位置: 代码迷 >> 综合 >> 一次改动引发的血案
  详细解决方案

一次改动引发的血案

热度:6   发布时间:2024-01-21 19:01:10.0

仅以此作为程序员警示文档。

摘要:

        改代码之前,一定要前前后后理解一遍原代码的逻辑,然后确定最优的方案,才下手去改,改完逻辑重新理一遍要自测! 对于新加的特性,要分析对原功能特性有没有影响。

需求背景:

       在网络安全趋向严格的背景下,需要将网安设备暴露在公网的系统升级端口进行收缩。也就是在开机启动一定时候后,关闭升级端口。只有人工前台配置了ssh网口区域,才开放升级端口。并且ssh网口区域也是有时效性的。

原升级场景:

        网安设备升级update daemon程序绑定升级端口 PORT 一直在线。在升级客户端完成身份认证后直接进入升级步骤。

方案及问题引入:

        在linux cron里面定时判断是否需要关闭 update daemon,如果需要关闭,则给update daemon 发送一个USR1信号。update daemon 添加一个 USR1 信号处理函数,来根据配置做相应的处理。

升级过程中的血案:

        这个是大概率出现的,问题在于升级的机制,升级过程中需要将新的脚本应用拷贝到网安设备上,一旦将定时检测是否关闭 update daemon 的脚本应用放到 cron 里面,它就有可能会马上开始运行,而此时升级过程并没有结束,虽然磁盘上替换了新update daemon,但设备(内存)运行的还是原 update daemon ,原 update daemon 没有对 USR1 做信号处理。所以问题来了:cron 的定时应用发了一个 USR1 信号,原 update daemon 直接默认挂了!  导致升级失败。

改动挖的三个坑:

        一个是没考虑新加的 USR1 信号对原update daemon的影响,在升级过程中任何的对原update daemon发 USR1 信号都是致命的错误(因发信号前做了删除pid操作,软狗也不会拉)。二个是没考虑升级过程中的漫长性(以计算机的速度而言),分步的拷贝执行脚本到linux cron定时任务是个有风险的操作。三是USR1信号对新的update daemon也是有害的,因为老新update daemon均执行了accept和select系统调用操作,当新update daemon正在传输数据时,接收USR1信号执行信号处理过程函数后,会使得select返回 errno == EINTR 错误。

更正措施:

        绕过的方式是,1控制升级过程中不要执行定时任务发信号给update daemon;2是将USR1信号改成不捕获默认忽略的信号比如 SIGCONT 或者 SIGWINCH

        根本的解决方式,还是要从方案上去改,不要采用发信号的方式去通知update daemon重新加载配置文件。

化不开的矛盾:

        一方面要求代码运行无误健壮性强,另一方面又要求在最短的时间产出来。在最短的时间内考虑周全是个绕不开的矛盾!

 

                                                 

  相关解决方案