整理 | 鄭麗媛
你能想象嗎:僅因一行程式碼,導致一家公司損失了至少 6000 萬美元?聽起來可能頗為匪夷所思,但這件事真實發生在了美國電信公司 AT&T 的身上。
自 1877 年成立以來,AT&T 從未發生過重大網路事故,為此公司也大力宣傳自家系統的可靠性和安全性。在這種背景下,到了上世紀 90 年代,當時 AT&T 已經佔據了美國 70% 的長途通訊量、電話呼叫轉發超過 11.5 億次,是當之無愧的美國最大電信通訊公司。
然而 1990 年 1 月 15 日 AT&T 發生的這場重大事故,顛覆了它在人們心中「安全可靠」的固有印象:1990 年 1 月 15 日,AT&T 出現大面積系統故障,網路持續癱瘓了 9 個小時,期間 6 萬多人的電話完全無法接通、7500 萬個電話被錯過、呼叫連接故障率高達 50%、500 個航班延誤……AT&T 因此損失了超過 6000 萬美元。
那麼這個價值 6000 萬美元的「罪魁禍首」,到底是哪行程式碼呢?


應管理層要求,程式碼沒有經過測試
在發生這場重大事故之前,AT&T 維持了一百多年的穩定可靠,主要利用當時先進的電子交換機和信號系統處理了大部分電話,其系統通常能在幾秒鐘內完成呼叫路由選擇。
按理說,既然如此 AT&T 的整個網路應該被設計得非常完善,即便單個交換機出現故障也不該引起系統崩潰,還能自主隔離有缺陷的交換機——一直以來,AT&T 也確實如此。但在事故發生前,AT&T 為了改善長途通話質量,將軟體進行了更新,而這個更新中存在一個致命 Bug。
事故當天,這個 Bug 從紐約的一臺交換機開始,導致整個網路都出現了故障,共影響了 114 臺交換機。最初,這臺紐約交換機的自檢程序發現它已接近負載極限,要執行復位併發出信號時,這個 Bug 引起了多米諾骨牌效應,導致大範圍的網路中斷。
你或許會問:那軟體更新前 AT&T 沒有測試嗎?這就是有趣的地方了:由於程式碼改動較小,因此按照管理層的要求,那次更新並沒有經過測試。

美國近一半主要通訊線路癱瘓
追根溯源,這個損失 6000 萬美元的事故原因,是在網路交換機上實施的軟體更新中出現了編碼錯誤。具體來說,這個 Bug 是由一個非常簡單的語法錯誤引起的:該 Bug 發生在 C 語言程序中,其中嵌套條件語句中的關鍵字 break 用法錯誤,由此導致了資料覆蓋和系統重置。
偽程式碼如下:

以上程式碼存在的問題:
如果環形緩衝區不為空,則跳過第 7 行的「if」語句,轉而執行第 10 行的 break 語句。
然而,為了使程序正常運行,本應執行第 11 行。
當 break 語句被執行,而不是處理傳入訊息併為可選參數設置指針時,資料(本應保留的指針)就會被覆蓋。
糾錯軟體識別出資料被覆蓋,便啟動關閉開關進行重置。由於整個網路中的所有交換機都使用了這個有缺陷的軟體,導致了連鎖復位反應,最終使整個網路系統癱瘓,讓問題變得更加複雜。
也就是說,儘管此前 AT&T 進行了嚴格測試,網路設計也非常靈活,但這次一行程式碼的疏忽還是導致了美國幾乎一半的主要通訊線路癱瘓。

網友:我敢打賭,沒有管理層因此被解僱
在經歷了 9 個小時的持續癱瘓後,AT&T 當時解決問題的方法是:讓工程師把交換機重裝回以前的軟體版本。而實際上,事後 AT&T 超過 100 人的技術團隊參與了此次事故分析,共花了兩週時間進行嚴格的程式碼閱讀、測試和複製,才最終弄清了 Bug 所在。
AT&T 的這次事故發生在 33 年前,可就算後來的公司擁有了更好工作流程,也難免會有漏網的 Bug,例如 2016 年 YouTube 也發生了首次全球故障。
作為這些發生重大故障的公司而言,其損失無疑是巨大的,因此每次也都會給他們帶去相應的教訓。但對大多數公司來說,很多故障歸根結底都是人為錯誤和流程漏洞造成的。
對於一行程式碼導致損失 6000 萬美元這件事,諸多網友也發表了自己的看法:
「這是人們在軟體開發中最具挑戰性的問題之一:事件原因和我們稱之為‘觸發器’之間存在巨大差異。導致問題的不是 1 行程式碼,而是這種環境使得 1 行程式碼就能夠‘觸發’問題。」
「問題在於一行程式碼 + 糟糕的管理,因為還有高層迫使工程師跳過測試。而且我敢打賭,沒有管理層因此被解僱。」
「最可悲的地方是:管理層要求繞過測試,因為程式碼變化太小了。」
那麼你對於這個導致了 6000 萬美元損失的事故,又有什麼看法嗎?
參考連結:
https://shimo.im/docs/9030J9eOGnc0n7kw
https://www.reddit.com/r/programming/comments/17uemqw/one_line_of_code_caused_att_to_lose_60_million/