ป้ายกำกับ: การเปลี่ยนแปลง

Therac-25: BUG ระดับตำนานTherac-25: BUG ระดับตำนาน

Therac-25 เป็นหนึ่งในเคสคลาสสิกและร้ายแรงที่สุดในประวัติศาสตร์วิศวกรรมซอฟต์แวร์ (ช่วงปี 1985–1987) เครื่องฉายรังสีรักษามะเร็งนี้ทำให้ผู้ป่วยได้รับรังสีเกินขนาดจนมีผู้เสียชีวิตและบาดเจ็บสาหัส

ความผิดพลาดหลักเกิดจากการที่วิศวกรนำระบบฮาร์ดแวร์ป้องกัน (Hardware Interlocks) ออก แล้วหันมาพึ่งพาระบบซอฟต์แวร์ในการควบคุมความปลอดภัยทั้งหมด โดยบักหลัก ๆ ในซอฟต์แวร์ (เขียนด้วยภาษา Assembly บนเครื่อง PDP-11) มีดังนี้ครับ


  1. บักการแย่งชิงทรัพยากร (Race Condition) จากการพิมพ์เร็ว
    • พฤติกรรม: บักนี้เกิดขึ้นในขั้นตอนการเตรียมเครื่องฉายรังสี โดยปกติเครื่องจะมี 2 โหมดคือ X-ray (ใช้พลังงานสูง 25 MeV และต้องมีแผ่นกรองรังสีบังไว้) กับ Electron (ใช้พลังงานต่ำ ยิงตรงเข้าผู้ป่วย)
    • กลไกของบัก:
      1. หากเจ้าหน้าที่เผลอกดเลือกโหมด X-ray (พิมพ์ X) ซอฟต์แวร์จะเริ่มสั่งให้มอเตอร์หมุนแผ่นกรองรังสีเข้าที่ ซึ่งใช้เวลาประมาณ 8 วินาที
      2. หากเจ้าหน้าที่รู้ตัวว่ากดผิด แล้วรีบกดปุ่มลูกศรขึ้น (Up Arrow) เพื่อไปแก้ไขโหมดเป็น Electron (พิมพ์ E) ภายในเวลา 8 วินาทีนั้น
      3. ซอฟต์แวร์ส่วนที่รับค่าหน้าจอ (UI) จะเปลี่ยนค่าแสดงผลเป็น Electron แต่ซอฟต์แวร์ส่วนควบคุมแม่เหล็กและปืนฉายแสงแฝง (Data Entry Subroutine) ไม่ได้รับรู้การเปลี่ยนแปลงนี้ เนื่องจากเขียนทับตัวแปรขัดกัน
    • ผลลัพธ์: เครื่องฉายรังสีปล่อยพลังงานสูงระดับ X-ray (25 MeV) แต่แผ่นกรองรังสีกลับไม่เลื่อนมาบัง เพราะคิดว่าเป็นโหมด Electron พลังงานต่ำ ทำให้ผู้ป่วยโดนรังสีเข้มข้นยิงตรงเข้าสู่ร่างกายโดยตรง (Overdose มากกว่าปกติเป็นร้อยเท่า)
  2. บักตัวนับล้น (Integer Overflow / Counter Rollover)
    • พฤติกรรม: บักนี้เกิดในโมดูลที่ทำหน้าที่ตรวจสอบความพร้อมของฮาร์ดแวร์ก่อนยิงรังสี (เรียกกันว่าข้อผิดพลาด Malfunction 54)
    • กลไกของบัก:
      1. ทุกครั้งที่ลูปตรวจสอบรันแล้วพบว่า “ฮาร์ดแวร์ยังไม่พร้อม” (เช่น แผ่นจานหมุนยังหมุนไม่เข้าที่) ซอฟต์แวร์จะเพิ่มค่าตัวแปรตัวนับ (Counter) ขึ้นทีละ 1
      2. ตัวแปรนี้เป็นแบบ 1 Byte (เก็บค่าได้สูงสุด 255)
      3. หากจังหวะที่เจ้าหน้าที่กดปุ่มสั่งยิงรังสี (Set/Command) ตรงกับจังหวะที่ลูปนี้ทำงานเป็นรอบที่ 256 พอดี ค่าของตัวแปรจะล้นกลับมาเป็น 0 (255 + 1 = 0 ในระบบเลขฐานสอง)
      4. ซอฟต์แวร์ตีความว่า 0 = ไม่มีข้อผิดพลาด/ฮาร์ดแวร์พร้อมแล้ว ทั้ง ๆ ที่ความจริงแผ่นจานหมุนยังอยู่ในตำแหน่งไฟส่องสว่าง (Field Light) ไม่ใช่ตำแหน่งรักษา
    • ผลลัพธ์: เครื่องทำการยิงรังสีพลังงานสูงใส่ผู้ป่วยในจังหวะที่ไม่มีระบบกำบังใด ๆ รองรับอยู่เลย
  3. บักด้านการออกแบบระบบและ 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

อ่านเพิ่มเติม