您曾经调试过的最困难的 bug 是什么?本文将介绍作者至今最困难的一次调试经历,希望从他怀疑硬件,再到怀疑软件到最终解决问题的过程中,能够为读者带来一些启示。
当我采访开发人员时,有时会问这样一个问题:“您曾经调试过的最困难的bug是什么?”大多数人都喜欢抛出一段特殊的缺失分号的血泪史,一个难以使用的 API,或者他们抓狂地修改旧的、无文档的代码经历。以下是我对这个问题的回答。
问题
问题来自一台有多个条形码读取器的机器。我们已经制造了 8 台这样的机器,其中一台在英国生产了几个月,而其余 7 台刚刚在中国安装完毕,而问题就出在了中国的其中一台机器上。
我们收到一份报告说其中一台机器投入生产后不久就停止了工作。客户说有一个他们无法解除的错误。这个错误会中止产品生产,每停机一分钟就会造成很大的经济损失。在任何时期,我们都不希望出现这种情况。我进行了远程操作,发现摄像头已经停止向 PLC(可编程逻辑控制器)发送结果,导致我们的软件用户界面发出警报。在这台机器上,将 ID40 作为数字 IO 予以连接以直接向 PLC 输出通过或失败的信号。这表明,故障可能与软件无关,但在这个行业摸爬滚打过几年的我知道:硬件和 PLC 通常都很稳定,95%的情况下是软件出了问题,所以我总是假设是软件出了问题。
从字面上看,这个故障意味着 PLC 认为触发了摄像头,在它再次触发摄像头之前没有收到数字 IO 结果,要么摄像头没有被 PLC 触发,要么摄像头没有输出通过或失败信号,要么 PLC 没有接收到通过或失败信号。我以为这是一次偶然,但如果是这种情况,重置和恢复就可以解决,而客户反映说,这么做没用。这台机器将继续生产下一个产品,然后再次停止。在远程观察到这一点后,我告诉他们重新启动这台机器。我对此没有合理的解释,希望这只是一次偶然(从来就没有偶然)。几个小时后,我又接到了电话,还是同一个问题。这一次,客户已经禁用了导致问题的摄像头,但是现在,第二个(托管的)摄像头显示出相同的错误。
调试第一天
就这一点,我的想法是:
相同的软件在英国已经运行了几个月,尽管在机器上略有不同。
这通常是一个摄像头的配置问题,但如果是这种情况,问题将出现在第一个产品,而不是运行了一个小时左右之后。
这发生在这台机器的所有摄像头上,所以它不是一个硬件故障。
经过办公室内的一番讨论之后,我们指示客户工程师启动摄像头。这不是让客户做的最简单的事情,尤其是在生产中。这些设备没有开关按钮,所以必须拧开一个项圈,断开电缆,然后重新连接,这似乎解决了问题,坚持了两个半小时。
有一个临时的解决方案,就是从车间中获取一个尚未发货的控制单元,并将其转移到办公室,然后我们部署它,假设它是一台出现问题的机器,连接摄像头并侵入脉冲发生器,模拟来自产品的物理机器的数字输入,这一切大约需要一天的时间。在这段时间里,我们发现这个问题几乎每两个半小时就会重复发生一次。与此同时,部署在中国的所有其他机器都在正常运行,一天 24 小时没有任何问题。
调试第二到四天
我们成功解决了这个问题,摄像头似乎锁定了。当脉冲发生器向它发送一个触发时,灯是固态的,触发灯不会亮。在这一点上,我非常确信这不是一个软件问题。我们请求 Microscan 提供技术支持,但仍在办公室进行测试。在接下来的几天,我们发现这个问题几乎每 4.5 千次触发出现一次,这就解释了为什么中国客户每两个半小时就会重复看到这个问题。我们还发现,只有当摄像头以一定速度触发时,才会发生这种情况。这解释了为什么这个问题只出现在 9 台机器中的 1 台上。
调试第五天
办公室里有很多关于 PLC 或摄像头的争论。双方都不能用任何理论来解释,相关主管建议将摄像头的网线从机器上断开。我们利用 Telnet 在批处理开始时使用以太网连接设置摄像头,发送摄像头正在读取的条形码中寻找的匹配字符串,使用以太网连接来获取摄像头看到的图像以及通过或失败的结果,这是通过 Web 请求完成的,直接输出到 PLC 的独立数字 IO 结果。在生产环境中,没有以太网连接不是一个可行的解决方案,因为用户需要查看图像,这让软件变得无用,因为就我们而言,这样就不进行产品检查了。然而,我们试了一下,效果不错,这个摄像头整夜都在运转,没再锁定。
调试第六天
我们重复测试多次,先连接以太网,然后断开,结果是可重现的,所以认为这肯定是一个软件问题。第一个理论是图像请求的每次触发都会导致问题,因此我们修改代码以删除该功能并将其部署到测试机器上。但这个问题仍然存在。这时,我们被难住了。以下是我们掌握的信息:
如果以太网连接在运行开始后断开(因此允许发送匹配字符串),则摄像头可以正常工作
在大约 4500 个产品(误差有 100 个左右)之后,保持以太网连接会导致摄像头锁定。
这毫无逻辑可言。在我们发送了匹配字符串,并删除请求图像的代码之后,我们没对连接做任何事情。
调试第七天
我在机器上安装了 Wireshark。我不知道为什么会这么做,大概只是一个猜测。我们仍然有图像请求的删除,所以我希望看到通过 Telnet 的一些摄像头的最初设置,然后什么也没有。我实际上看到的是通过 Telnet 从摄像头向我们发送的数据流。检查数据很明显,它通过我们打开的 Telnet 连接向我们发送匹配结果来配置摄像头设置。
这种行为在我们能找到的任何地方都没有记录,当然我们也没有刻意要求这么做。我们甚至没有监听响应。
我们研究了如何与摄像头通信。我们在第一次需要的时候就打开了一个 TCP 连接,并让它通过应用程序更改摄像头设置。我们对此进行了修改,以便在发送完所需信息后关闭连接,如果需要则重新打开连接。在接下来的几天,我们对它进行了彻底测试。
结论
我还是不明白这是怎么把摄像头锁定的。我们通过 Telnet 接收 TCP 结果,但是我们没有读取流,这是在缓冲中积累起来的吗?这是如何导致摄像头锁定的?我仍然不能回答这些问题。
我们向客户部署了新版本的软件,在撰写本文时,它已经运行了近一年,不需要进一步修改。从那时起,它已经生产了大约 1000 万件产品。我从中学到的是负载测试的重要性。我们测试了机器,但没有达到所需的水平。我们在办公室运行了几千个产品,但客户希望在一定时间内批处理运行 180k 个产品,我们没有测试过任何接近这个水平的连续操作。
从那以后,我们询问每个客户最大的批量处理有多少,然后我们用两倍的量来测试。
评论 1 条评论