Therac-25 เป็นหนึ่งในเคสคลาสสิกและร้ายแรงที่สุดในประวัติศาสตร์วิศวกรรมซอฟต์แวร์ (ช่วงปี 1985–1987) เครื่องฉายรังสีรักษามะเร็งนี้ทำให้ผู้ป่วยได้รับรังสีเกินขนาดจนมีผู้เสียชีวิตและบาดเจ็บสาหัส
ความผิดพลาดหลักเกิดจากการที่วิศวกรนำระบบฮาร์ดแวร์ป้องกัน (Hardware Interlocks) ออก แล้วหันมาพึ่งพาระบบซอฟต์แวร์ในการควบคุมความปลอดภัยทั้งหมด โดยบักหลัก ๆ ในซอฟต์แวร์ (เขียนด้วยภาษา Assembly บนเครื่อง PDP-11) มีดังนี้ครับ
- บักการแย่งชิงทรัพยากร (Race Condition) จากการพิมพ์เร็ว
- พฤติกรรม: บักนี้เกิดขึ้นในขั้นตอนการเตรียมเครื่องฉายรังสี โดยปกติเครื่องจะมี 2 โหมดคือ X-ray (ใช้พลังงานสูง 25 MeV และต้องมีแผ่นกรองรังสีบังไว้) กับ Electron (ใช้พลังงานต่ำ ยิงตรงเข้าผู้ป่วย)
- กลไกของบัก:
- หากเจ้าหน้าที่เผลอกดเลือกโหมด X-ray (พิมพ์
X) ซอฟต์แวร์จะเริ่มสั่งให้มอเตอร์หมุนแผ่นกรองรังสีเข้าที่ ซึ่งใช้เวลาประมาณ 8 วินาที - หากเจ้าหน้าที่รู้ตัวว่ากดผิด แล้วรีบกดปุ่มลูกศรขึ้น (Up Arrow) เพื่อไปแก้ไขโหมดเป็น Electron (พิมพ์
E) ภายในเวลา 8 วินาทีนั้น - ซอฟต์แวร์ส่วนที่รับค่าหน้าจอ (UI) จะเปลี่ยนค่าแสดงผลเป็น Electron แต่ซอฟต์แวร์ส่วนควบคุมแม่เหล็กและปืนฉายแสงแฝง (Data Entry Subroutine) ไม่ได้รับรู้การเปลี่ยนแปลงนี้ เนื่องจากเขียนทับตัวแปรขัดกัน
- หากเจ้าหน้าที่เผลอกดเลือกโหมด X-ray (พิมพ์
- ผลลัพธ์: เครื่องฉายรังสีปล่อยพลังงานสูงระดับ X-ray (25 MeV) แต่แผ่นกรองรังสีกลับไม่เลื่อนมาบัง เพราะคิดว่าเป็นโหมด Electron พลังงานต่ำ ทำให้ผู้ป่วยโดนรังสีเข้มข้นยิงตรงเข้าสู่ร่างกายโดยตรง (Overdose มากกว่าปกติเป็นร้อยเท่า)
- บักตัวนับล้น (Integer Overflow / Counter Rollover)
- พฤติกรรม: บักนี้เกิดในโมดูลที่ทำหน้าที่ตรวจสอบความพร้อมของฮาร์ดแวร์ก่อนยิงรังสี (เรียกกันว่าข้อผิดพลาด Malfunction 54)
- กลไกของบัก:
- ทุกครั้งที่ลูปตรวจสอบรันแล้วพบว่า “ฮาร์ดแวร์ยังไม่พร้อม” (เช่น แผ่นจานหมุนยังหมุนไม่เข้าที่) ซอฟต์แวร์จะเพิ่มค่าตัวแปรตัวนับ (Counter) ขึ้นทีละ 1
- ตัวแปรนี้เป็นแบบ 1 Byte (เก็บค่าได้สูงสุด 255)
- หากจังหวะที่เจ้าหน้าที่กดปุ่มสั่งยิงรังสี (Set/Command) ตรงกับจังหวะที่ลูปนี้ทำงานเป็นรอบที่ 256 พอดี ค่าของตัวแปรจะล้นกลับมาเป็น 0 (
255 + 1 = 0ในระบบเลขฐานสอง) - ซอฟต์แวร์ตีความว่า
0 = ไม่มีข้อผิดพลาด/ฮาร์ดแวร์พร้อมแล้วทั้ง ๆ ที่ความจริงแผ่นจานหมุนยังอยู่ในตำแหน่งไฟส่องสว่าง (Field Light) ไม่ใช่ตำแหน่งรักษา
- ผลลัพธ์: เครื่องทำการยิงรังสีพลังงานสูงใส่ผู้ป่วยในจังหวะที่ไม่มีระบบกำบังใด ๆ รองรับอยู่เลย
- บักด้านการออกแบบระบบและ User Interface (UI/UX)
นอกจากข้อผิดพลาดเชิงโค้ด (Coding Bugs) ข้างต้นแล้ว ระบบยังมีช่องโหว่ร้ายแรงด้านสถาปัตยกรรมซอฟต์แวร์ดังนี้ครับ- การสลับโหมดที่ง่ายเกินไป: ซอฟต์แวร์ใช้ระบบจำลองคีย์บอร์ดแบบอัตโนมัติ (Carriage Return Macro) หากเจ้าหน้าที่กด Enter รัว ๆ ระบบจะข้ามขั้นตอนการตรวจสอบความปลอดภัยทางกายภาพไปทันที
- ข้อความแจ้งเตือนที่คลุมเครือ: เมื่อเกิดการฉายรังสีพลาด หน้าจอจะแสดงคำว่า
MALFUNCTION 54หรือTREATMENT SUSPENDโดยไม่มีคำอธิบาย และระบบปล่อยให้เจ้าหน้าที่กดปุ่มP(Proceed) เพื่อยิงซ้ำได้ทันที (ทำให้ผู้ป่วยบางรายโดนรังสีซ้ำเป็นรอบที่สอง) - การนำโค้ดเก่ามาใช้ซ้ำโดยไม่ตรวจสอบ (Software Reuse): AECL นำซอฟต์แวร์ของรุ่นก่อนหน้า (Therac-20) มาใช้เกือบทั้งหมด โดยไม่ทันคิดว่าใน Therac-20 นั้นมีบัก Race Condition นี้อยู่แล้ว เพียงแต่ในรุ่นเก่ามีระบบฮาร์ดแวร์ป้องกัน (Hardware Interlocks) คอยตัดไฟอยู่ บักในซอฟต์แวร์จึงไม่เคยแสดงผลร้ายออกมา จนกระทั่งถูกถอดฮาร์ดแวร์ออกในรุ่น Therac-25
อ่านเพิ่มเติม