NF

地方で働くプログラマ

GW前半が終わったらしい

近所の喫茶店日記。
5月入って行ってみたら、またお休みが半月伸びてた。(前回4/24日記参照)
 
GW後半もあっという間に終わりそう。
 
ーーー
Rustネタ
GoとRust - 並行プログラミング編
非同期 Rust パターン - Qiita
Rustの非同期プログラミングをマスターする - OPTiM TECH BLOG
 
ーーー
The Therac-25 Incident - The Daily WTF
The Worst Computer Bugs in History: Race conditions in Therac-25 | Bugsnag Blog
Therac-25という、ソフトウェアのバグによる?死亡事故を起こした医療機器の話。
事故自体は昔知ったけど、具体的にどんなバグか知らなかったし、wikipediaを始め日本語だとバグ自体の詳しい説明がない(本質的な問題は開発とかフェイルセイフとかだからだろうけど)のでちょっと調べた。組み込み界隈では有名なんだろうか。
取り合えず、「Race conditions」と「Byte overflow」があるので、この2つがコード上の問題そう。
 
http://sunnyday.mit.edu/papers/therac.pdf
http://courses.cs.vt.edu/~cs3604/lib/Therac_25/Therac_1.html(InternetArchive経由)
一番詳しい文書はこれっぽい。上は検索できない(けど画像が鮮明)ので下を読んだ。
1つ目のバグ(レースコンディション)が2ページ目「The software problem.」の部分、2つ目のバグ(バイトオーバーフロー)が3ページ目の「The Yakima software problem.」の部分かな。
 
1つ目。
なんか難しくてちゃんと理解してないが、TreatタスクとKeyHandlerタスクがあって、Treatタスクは状態を持ってる。Treatタスクはデータ入力が完了したらDatent=1からSetUpTest=2に進める、未完了ならもう一度やり直す、という実装だけど、このフラグ管理が良くなくて(Figure.3のPtimeサブルーチンが「bending magnet flag」をクリアが問題?)、入力がし直されてされても(前の)入力のままSetUpTestに進んじゃうっぽい。
あとオペレータが慣れてて早く入力しちゃう場合のみ起こるらしいけど、読み解けてない。
 
2つ目。
1つ目のバグの後色々あったが、暫定処置みたいな対応をして使われ続けてたけど、もう1つバグがあった模様。Class3とF$malという共有変数があって、前述のTreatタスクがSetUpTest=2の時、Class3を毎回インクリメントする(これは数百回実行される)。別のタスクHKeperがいて、Class3が0以外の場合にChkcolサブルーチンを実行して、状態が不整合ならF$malの9bit目をセットする。Treatタスクはここがセットされてない時(=状態整合している)だけ、SetUpDone=3に状態を進める。
ここで、Class3は8bit変数なので256回目で0になってしまい、運悪くこのタイミングでオペレータが設定操作をするとHKeperのChkcol実行がパスされてしまい、F$malが設定されず、状態不整合のままSetUpDone=3に進んでしまう、でいいのかな。
 
そんな感じで、なんか有りがち(30年以上たってる今でも…)なミスが原因だったっぽい。上のレポートから読み取れる被害としては、最初の事故が1985年で年内に3件、1986年に2件、1987年に1件が発生して、合計4人が死亡してる。wikipedia他とかだと5人とか6人とかになっててよく分からん。
 
この事故、全体を見ても教訓がありすぎてそれこそ頭がオーバーフローしそうになる。なのに、未だに同レベルの問題を仕事で目にするし悲しくなるな。
bugsnagの方にこれ系のシリーズが載ってるので、他も後で読もう。