【译文】一行代码如何造成 6000 万美元的损失
1990 年 1 月 15 日,AT&T 的新泽西运营中心检测到大范围的系统故障,网络显示屏上出现了大量红色警告。
尽管试图排除故障,但网络故障仍持续了 9 个小时,导致呼叫连接故障率达到 50%。
AT&T 因此损失超过 6000 万美元,6 万多名美国人的电话完全无法接通。
此外,500 个航班延误,8.5 万人受到影响。
按理说,AT&T 的长途网络是高效率的典范,它利用先进的电子交换机和信号系统处理了全国大部分的电话。该系统通常能在几秒钟内完成电话路由选择。
然而,就在这一天,从纽约的一个交换机开始,整个网络出现了故障。这是由于最近一次更新中的一个软件错误造成的,该错误影响了网络中的 114 个交换机。当纽约的交换机复位并发出信号时,这个错误引发了多米诺骨牌效应,导致大范围的网络中断。
这个软件补丁经过了层层测试,却没有被发现。这一事件尤其令人吃惊,因为 AT&T 以严格的测试而闻名。
问题所在
追根溯源,原因在于网络交换机实施的软件更新中出现了编码错误。
该错误发生在一个 C 语言程序中,涉及嵌套条件语句中一个错位的中断语句,导致数据覆盖和系统重置。
伪代码
1 while (ring接收缓冲区未清空
and side缓冲区未空):
2 初始化指向side缓冲区或ring接收缓冲区中第一个报文的指针
or ring形接收缓冲区
3 获取缓冲区副本
4 switch (message):
5 case (incoming_message):
6 if (发送停止服务开关):
7 if (ring 写缓冲区为空):
8 send "in service" to status map
9 else:
10 break // 错误出在这里!
END IF
11 处理接收到的信息,设置指针指向
可选参数
12 break
END SWITCH
13 做可选参数工作
问题是
- 如果ring写入缓冲区不是空的,那么第 7 行的 `if` 语句就会被跳过,取而代之的是第 10 行的中断语句。
- 然而,为了使程序正常运行,本应执行第 11 行。
- 当中断语句被执行,而不是处理传入的信息并为可选参数设置指针时,数据(本应保留的指针)就会被覆盖
- 纠错软件识别出数据被覆盖,并启动关闭开关进行重置。由于网络中的所有交换机都使用了这种有缺陷的软件,导致了连锁重置反应,最终瘫痪了整个网络系统,使问题变得更加复杂。
尽管网络的设计具有很强的恢复能力,但一行代码还是导致了半个国家的主要通信线路瘫痪。
修复
工程师们花了 9 个小时才使 AT&T 的系统完全恢复正常。他们主要是通过将交换机回滚到之前的代码工作版本来实现的。
实际上,软件工程师花了两周时间进行严格的代码阅读、测试和复制,才真正弄清了错误所在。
结论
对于 AT&T 来说,不幸的是,这还不是他们 90 年代最大的系统崩溃。在这十年的后期,他们还遇到了更多的问题。
实际上,导致系统崩溃的并不是一行代码。而是流程的失败。
如今的公司拥有更好的流程,但即便如此,还是会有漏洞漏网。谷歌撰写了一篇关于网站可靠性工程 20 年的回顾文章,对 2016 年 YouTube 的首次全球故障进行了反思。
对于公司来说,故障的规模是巨大的,每次故障都会给我们带来教训。然而,对于大多数公司来说,故障归根结底是人为错误和流程漏洞造成的。
本文文字及图片出自 How one line of code caused a $60 million loss
你也许感兴趣的:
- 我是如何在第一款登月游戏中发现一个 55 年前的漏洞的
- 【外评】航空公司总是把 101 岁的老太太误认为婴儿
- 【译文】经常嗡嗡叫的虫子(bug)
- 【程序员搞笑图片】要不要上报?
- 【译文】满月时,代码工作异常
- 【译文】bug 经济学
- 我所见过的最奇怪的Bug
- Google在一个函数中放入2万个变量,引发Firefox大崩溃
- 离职两年后,程序员遭前东家索赔:Bug 是你写的
- 40岁程序员谈修bug的心态问题
你对本文的反应是: