ความเป็นไปได้ของบั๊กใน std::shared_mutex บน Windows
- ทีมซอฟต์แวร์ทีมหนึ่งพบพฤติกรรมที่ไม่คาดคิดซึ่งเกี่ยวข้องกับ
std::shared_mutex บน Windows
- ปัญหานี้เกิดขึ้นเฉพาะใน MSVC และไม่เกิดใน MinGW หรือแพลตฟอร์มอื่น
- เมื่อเธรดหลักเข้าถึง exclusive lock แล้วมี child thread หลายตัวพยายามเข้าถึง shared lock จะเกิด "deadlock" ประมาณ 1 ครั้งในทุก ๆ 1000 ครั้ง
- เมื่อเกิด deadlock จะมี child thread เพียง 1 ตัวเท่านั้นที่เข้าถึง shared lock ได้สำเร็จ ส่วน child thread ที่เหลือจะถูกบล็อกอยู่ที่
lock_shared() ตลอดไป
- ปัญหานี้สังเกตได้ทั้งเมื่อใช้
std::shared_mutex, std::shared_lock/std::unique_lock หรือเมื่อเรียกใช้ฟังก์ชัน SRW โดยตรง
ตัวอย่างโค้ดและการทำซ้ำบั๊ก
- มีการให้โค้ดง่าย ๆ ที่สามารถใช้ทำให้ปัญหานี้เกิดซ้ำได้
- โค้ดนี้จะวนซ้ำขั้นตอนที่เธรดหลักเข้าถึง exclusive lock จากนั้น child thread หลายตัวเข้าถึง shared lock แล้วปล่อย lock
- โค้ดนี้แสดงบั๊กที่เกี่ยวข้องกับ
std::shared_mutex เฉพาะใน implementation ของ Windows MSVC เท่านั้น
ความเห็นจากผู้เชี่ยวชาญ
- นักพัฒนา STL ระบุว่าปัญหานี้ดูเหมือนจะเป็นบั๊กของ Windows API
- มีการพูดคุยถึงขั้นตอนที่เหมาะสมในการรายงานบั๊ก และนักพัฒนา STL ได้รายงานบั๊กนี้ภายในแล้ว
- ผู้ใช้อื่น ๆ ได้ช่วยตรวจสอบปัญหานี้อย่างละเอียด และช่วยไล่ขอบเขตไปยังบั๊กเฉพาะจุดใน implementation ของ SRWLock
ความเห็นของ GN⁺
- บทความนี้ให้ข้อมูลที่สำคัญอย่างยิ่งสำหรับนักพัฒนา C++ โดยเฉพาะ เพราะบั๊กที่อาจมีอยู่ใน
std::shared_mutex สามารถส่งผลต่อกลไกการซิงโครไนซ์ของแอปพลิเคชันแบบมัลติเธรดได้
- หากยืนยันว่าบั๊กนี้มีอยู่จริง ก็อาจกระทบต่อความน่าเชื่อถือของ implementation ในไลบรารีมาตรฐาน C++ นักพัฒนาอาจจำเป็นต้องตระหนักถึงปัญหานี้และพิจารณากลไกการซิงโครไนซ์ทางเลือก
- ปัญหานี้อาจสำคัญเป็นพิเศษในระบบประสิทธิภาพสูงหรือระบบเรียลไทม์ เพราะ deadlock อาจก่อให้เกิดผลกระทบร้ายแรงได้
- ก่อนนำเทคโนโลยีนี้ไปใช้ นักพัฒนาควรทดสอบกับแพลตฟอร์มและคอมไพเลอร์ที่เกี่ยวข้องอย่างกว้างขวาง เพื่อยืนยันว่าไม่มีบั๊กประเภทนี้
- เพื่อแก้ปัญหาลักษณะนี้ นักพัฒนาอาจพิจารณาไลบรารีซิงโครไนซ์ทางเลือกอย่าง Boost ซึ่งผ่านการทดสอบอย่างกว้างขวางและถูกใช้งานบนหลายแพลตฟอร์ม จึงอาจเป็นทางเลือกที่เสถียรกว่าสำหรับปัญหาประเภทนี้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ผู้ใช้คนหนึ่งสงสัยว่าทำไมปัญหาพื้นฐานเช่นนี้จึงไม่ถูกค้นพบมาเป็นเวลานาน และกล่าวถึงคำตอบที่น่าเชื่อถือซึ่งผู้ใช้อีกรายให้ไว้ โดยชี้ให้เห็นว่าเธรดที่พยายามล็อกในโหมดแชร์อาจเผลอได้ล็อกในโหมดเอกสิทธิ์แทนได้ ซึ่งเกิดจากการซ้อนทับกันของการดำเนินการทดสอบบิตและตั้งค่าบิตแบบอะตอมิก เมื่อเธรดที่ขอรับโหมดแชร์และเธรดที่ปล่อยโหมดเอกสิทธิ์ทำงานพร้อมกัน
ผู้ใช้อีกคนระบุว่าไม่แปลกใจกับบั๊กที่ละเอียดอ่อนใน Reader/Writer lock และเล่าประสบการณ์ที่เคยทำงานกับการอิมพลีเมนต์ภายในบนพื้นฐาน Win32 ก่อนยุค C++11 และ
std::shared_mutexเขาเผยว่ามีประสบการณ์ไม่ดีกับ shared lock มากพอจนพยายามหลีกเลี่ยง เว้นแต่จำเป็นจริง ๆผู้ใช้คนหนึ่งชี้ว่าชื่อเรื่องชวนให้เข้าใจผิด โดยอธิบายว่าบั๊กจริงอยู่ใน slim reader/writer (SRW) lock ของ Windows API และถูกค้นพบเพราะ
std::shared_mutexถูกอิมพลีเมนต์โดยใช้ SRW lock พนักงาน Microsoft ยืนยันว่าบั๊กนี้ได้ถูกส่งต่อภายในไปยังทีม Windows API แล้วผู้ใช้คนหนึ่งสงสัยว่าในการอิมพลีเมนต์ของ WINE จะเกิดปัญหาเดียวกันหรือไม่ และบอกว่าอยากทดสอบบนชุดติดตั้ง XP แบบปรับแต่งเองของเขาด้วย ซึ่งได้เพิ่มส่วนขยายหลายอย่างรวมถึง SRW API และเคยแพตช์เคอร์เนลเพื่อแก้ race condition ที่ทำให้ keyed event API ซึ่งอิงกับการอิมพลีเมนต์ SRW เกิด deadlock
มีการชี้ว่าโปรแกรมนี้มีบั๊กอยู่ โดยมีการใช้ตัวแปรที่ไม่เป็น atomic ปะปนกับตัวแปร atomic ในลูปตรวจสอบ
yield()และตัวแปรที่ไม่เป็น atomic ไม่รับประกัน cache coherence กับเธรดอื่น ส่งผลให้ลูปอาจทำงานไม่สิ้นสุดผู้ใช้คนหนึ่งกล่าวว่าบั๊กนี้ย้อนกลับไปได้ถึง Vista เวอร์ชันปี 2008 และแสดงความประหลาดใจที่ไม่มีใครค้นพบบั๊กนี้ตลอดเวลาที่ยาวนานเช่นนั้น เขาระบุว่าในการใช้งาน rwlock ทั่วไป อาจเกิดกรณีสุ่มที่ไม่สามารถได้ shared lock แต่จะไม่เกิด deadlock
ผู้ใช้คนหนึ่งกล่าวว่าการรายงานบั๊กเกี่ยวกับ Windows API นั้นยากมาก และแม้จะถูกแนะนำให้รายงานผ่าน Feedback Hub ก็วิจารณ์ว่าวิธีนี้แทบไม่ได้ผล ผู้ใช้รายนี้ได้รายงานบั๊กว่า SRWLOCK อาจเกิด deadlock ได้เมื่อเธรดอ่านหลายตัวพยายามรับ shared ownership พร้อมกัน หลังจากเจ้าของแบบเอกสิทธิ์ปล่อยความเป็นเจ้าของแล้ว
ผู้ใช้คนหนึ่งรำลึกว่าในอดีตเมื่อซื้อผลิตภัณฑ์ของ MS จะได้รับ support incident และหากพบว่าเป็นบั๊กจริงก็จะได้รับเงินคืนสำหรับ incident นั้น เขากล่าวว่านี่เป็นระบบที่ดี ทั้งมีประโยชน์ต่อผู้พัฒนาและให้ฟีดแบ็กแก่ MS เพื่อค้นหาปัญหาจริงและปรับปรุงเอกสาร พร้อมตั้งคำถามว่าโปรแกรมนี้ยังมีอยู่หรือไม่
ท้ายที่สุด ผู้ใช้คนหนึ่งแสดงความผิดหวังต่อความยากลำบากในการรายงานบั๊กของ Windows API