เจาะลึกข้อผิดพลาดเงียบใน iOS 17 จากการใช้ @Dependency และ withTaskGroup
นักพัฒนา Swift ที่ใช้งานไลบรารี swift-dependencies อาจเจอแครชปริศนาเฉพาะบน iOS 17 เมื่อเรียกใช้งานใน Task Group พร้อมวิธีแก้ไขป้องกัน

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- พบบั๊กเงียบใน iOS 17 จากการเรียกใช้งาน @Dependency ภายใน withTaskGroup
- ระบบ Concurrency ของ Swift จะบล็อกการผูกค่า Task-local ระหว่างอยู่ใน Task Group
- โค้ดจะรันได้ปกติบน iOS 18 แต่จะเกิด Fatal Error ทันทีบน iOS 17
- วิธีแก้คือนำการดึง Dependency ออกมาทำภายนอก Task Group ก่อนเสมอ
นักพัฒนาซอฟต์แวร์ที่ใช้ไลบรารี swift-dependencies ของ Point-Free ในภาษา Swift อาจต้องระวังข้อผิดพลาดชวนปวดหัวที่เกิดขึ้นเฉพาะกับผู้ใช้งานระบบปฏิบัติการ iOS 17 เท่านั้น โดยข้อผิดพลาดนี้จะซ่อนตัวอย่างเงียบๆ และไม่มีคำเตือนใดๆ ตอนคอมไพล์โค้ด ทำให้ตรวจสอบได้ยากหากอุปกรณ์สำหรับพัฒนาอัปเดตเป็น iOS 18 ไปหมดแล้ว
สแต็กทราซ (Stack trace) จากข้อผิดพลาดนี้จะชี้ลึกไปยังระบบรันไทม์ Concurrency ของ Swift โดยตรงในฟังก์ชัน swift_task_reportIllegalTaskLocalBindingWithinWithTaskGroup ทั้งที่โค้ดส่วนใหญ่ไม่ได้เข้าไปยุ่งเกี่ยวกับค่า Task-local โดยตรง แต่สาเหตุกลับมาจากการอ่านพรอมเพอร์ตี้ @Dependency ภายในขอบเขตของ withThrowingTaskGroup หรือแม้กระทั่งการใส่ไว้ในแคปเจอร์ลิสต์ของโคลเจอร์ addTask

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
เบื้องหลังการทำงานของ swift-dependencies นั้นอาศัยระบบ Task-local ของ Swift เพื่อช่วยจัดการเรื่อง Dependency Injection ทำให้เราสามารถเขียนโค้ดสั้นๆ เช่น:
- ประกาศใช้งานผ่าน
@Observable final class MyViewModel - ซ่อนรายละเอียดการทำงานไว้เบื้องหลังพรอมเพอร์ตี้แร็ปเปอร์ (Property Wrapper)
- รองรับการจำกัดขอบเขตการทับซ้อนของ Dependency ได้อย่างยืดหยุ่น
การที่ฟังก์ชัน @Dependency ทำงานได้ราบรื่นบน iOS 18 แต่ออกอาการแครชบน iOS 17 สะท้อนให้เห็นถึงความเข้มงวดของระบบโครงสร้างการทำงานร่วมกัน (Structured Concurrency) ในแต่ละเวอร์ชัน ระบบปฏิบัติการรุ่นเก่าจะป้องกันไม่ให้มีการสร้างตัวผูกค่า Task-local ใหม่ในขณะที่ Task Group กำลังสร้างเธรดลูก เพื่อป้องกันความกำกวมในการสืบทอดข้อมูล ซึ่งเป็นสิ่งที่นักพัฒนาควรรู้เท่าทันเมื่อใช้งานไลบรารีภายนอกที่ซ่อนกลไกซับซ้อนไว้ข้างใต้
กฎเหล็กในการป้องกันปัญหานี้คือ การดึงค่า Dependency ทั้งหมดให้เรียบร้อยก่อนที่จะกระโดดเข้าไปในบล็อกของ Task Group การกระทำดังกล่าวจะทำให้โค้ดทำงานได้อย่างถูกต้องและปลอดภัยเหมือนกันทั้งบน iOS 17 และ iOS 18 นอกจากนี้ นักพัฒนาสามารถใช้คำสั่งค้นหาโค้ดในโปรเจกต์เพื่อตรวจสอบจุดที่อาจมีความเสี่ยง เช่น การใช้คำสั่ง grep เพื่อหาไฟล์ที่มีทั้ง withTaskGroup และ @Dependency อยู่ร่วมกัน
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น