2 คะแนน โดย GN⁺ 2024-03-04 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

ความเป็นไปได้ของบั๊กใน 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 ความคิดเห็น

 
GN⁺ 2024-03-04
ความคิดเห็นจาก Hacker News
  • ผู้ใช้คนหนึ่งสงสัยว่าทำไมปัญหาพื้นฐานเช่นนี้จึงไม่ถูกค้นพบมาเป็นเวลานาน และกล่าวถึงคำตอบที่น่าเชื่อถือซึ่งผู้ใช้อีกรายให้ไว้ โดยชี้ให้เห็นว่าเธรดที่พยายามล็อกในโหมดแชร์อาจเผลอได้ล็อกในโหมดเอกสิทธิ์แทนได้ ซึ่งเกิดจากการซ้อนทับกันของการดำเนินการทดสอบบิตและตั้งค่าบิตแบบอะตอมิก เมื่อเธรดที่ขอรับโหมดแชร์และเธรดที่ปล่อยโหมดเอกสิทธิ์ทำงานพร้อมกัน

    • ผู้ใช้คนหนึ่งอธิบายว่ามีโค้ดสำหรับทำซ้ำปัญหาที่ทำให้เธรดอื่นทั้งหมดรอเพื่อให้ได้ shared lock ขณะกำลังได้ shared lock เช่นกัน ซึ่งทำให้หากเธรดทำงานใดเธรดหนึ่งเผลอได้ exclusive lock ก็อาจเข้าสู่ภาวะ deadlock ได้ ในกรณีการใช้งานทั่วไป เธรดจะไม่ได้รอกันเอง จึงไม่เกิด deadlock
  • ผู้ใช้อีกคนระบุว่าไม่แปลกใจกับบั๊กที่ละเอียดอ่อนใน Reader/Writer lock และเล่าประสบการณ์ที่เคยทำงานกับการอิมพลีเมนต์ภายในบนพื้นฐาน Win32 ก่อนยุค C++11 และ std::shared_mutex เขาเผยว่ามีประสบการณ์ไม่ดีกับ shared lock มากพอจนพยายามหลีกเลี่ยง เว้นแต่จำเป็นจริง ๆ

    • ผู้ใช้คนหนึ่งเล่าประสบการณ์ด้านลบเกี่ยวกับ shared lock โดยระบุว่าประสิทธิภาพของ std::shared_mutex แย่กว่า std::mutex อย่างชัดเจน จนการทำ double buffering กับข้อมูลกลับเร็วกว่า
  • ผู้ใช้คนหนึ่งชี้ว่าชื่อเรื่องชวนให้เข้าใจผิด โดยอธิบายว่าบั๊กจริงอยู่ใน slim reader/writer (SRW) lock ของ Windows API และถูกค้นพบเพราะ std::shared_mutex ถูกอิมพลีเมนต์โดยใช้ SRW lock พนักงาน Microsoft ยืนยันว่าบั๊กนี้ได้ถูกส่งต่อภายในไปยังทีม Windows API แล้ว

    • ผู้ใช้คนหนึ่งชี้ถึงชื่อเรื่องที่ชวนให้เข้าใจผิด และกล่าวว่าปัญหาที่แท้จริงอยู่ที่ SRW lock ของ Windows API โดยมีพนักงาน Microsoft ยืนยันว่าบั๊กดังกล่าวได้ถูกรายงานแล้ว
  • ผู้ใช้คนหนึ่งสงสัยว่าในการอิมพลีเมนต์ของ WINE จะเกิดปัญหาเดียวกันหรือไม่ และบอกว่าอยากทดสอบบนชุดติดตั้ง XP แบบปรับแต่งเองของเขาด้วย ซึ่งได้เพิ่มส่วนขยายหลายอย่างรวมถึง SRW API และเคยแพตช์เคอร์เนลเพื่อแก้ race condition ที่ทำให้ keyed event API ซึ่งอิงกับการอิมพลีเมนต์ SRW เกิด deadlock

    • ผู้ใช้คนหนึ่งสงสัยว่าการอิมพลีเมนต์ของ WINE จะมีปัญหาเดียวกันหรือไม่ และบอกว่าอยากทดสอบบนชุดติดตั้ง XP แบบปรับแต่งเองของเขา ซึ่งเพิ่มส่วนขยายหลายอย่างรวมถึง SRW API และแพตช์เคอร์เนลเพื่อแก้ race condition ที่ทำให้ keyed event API ซึ่งอิงกับการอิมพลีเมนต์ SRW เกิด deadlock
  • มีการชี้ว่าโปรแกรมนี้มีบั๊กอยู่ โดยมีการใช้ตัวแปรที่ไม่เป็น atomic ปะปนกับตัวแปร atomic ในลูปตรวจสอบ yield() และตัวแปรที่ไม่เป็น atomic ไม่รับประกัน cache coherence กับเธรดอื่น ส่งผลให้ลูปอาจทำงานไม่สิ้นสุด

    • ผู้ใช้คนหนึ่งชี้บั๊กในโปรแกรมและอธิบายปัญหาที่เกิดจากการใช้ตัวแปรที่ไม่เป็น atomic ปะปนกับตัวแปร atomic โดยกล่าวว่าตัวแปรที่ไม่เป็น atomic ไม่รับประกัน cache coherence ทำให้ลูปอาจวนไม่รู้จบ
  • ผู้ใช้คนหนึ่งกล่าวว่าบั๊กนี้ย้อนกลับไปได้ถึง Vista เวอร์ชันปี 2008 และแสดงความประหลาดใจที่ไม่มีใครค้นพบบั๊กนี้ตลอดเวลาที่ยาวนานเช่นนั้น เขาระบุว่าในการใช้งาน rwlock ทั่วไป อาจเกิดกรณีสุ่มที่ไม่สามารถได้ shared lock แต่จะไม่เกิด deadlock

    • ผู้ใช้คนหนึ่งกล่าวว่าบั๊กนี้ย้อนกลับไปถึง Vista และแสดงความประหลาดใจที่มันไม่ถูกค้นพบมาเป็นเวลานาน พร้อมระบุว่าในการใช้ rwlock ทั่วไป จะไม่เกิด deadlock แต่สามารถเกิดกรณีที่ไม่ได้ shared lock ได้
  • ผู้ใช้คนหนึ่งกล่าวว่าการรายงานบั๊กเกี่ยวกับ Windows API นั้นยากมาก และแม้จะถูกแนะนำให้รายงานผ่าน Feedback Hub ก็วิจารณ์ว่าวิธีนี้แทบไม่ได้ผล ผู้ใช้รายนี้ได้รายงานบั๊กว่า SRWLOCK อาจเกิด deadlock ได้เมื่อเธรดอ่านหลายตัวพยายามรับ shared ownership พร้อมกัน หลังจากเจ้าของแบบเอกสิทธิ์ปล่อยความเป็นเจ้าของแล้ว

    • ผู้ใช้คนหนึ่งกล่าวว่าการรายงานบั๊กของ Windows API นั้นยากมาก และวิจารณ์ว่าการรายงานผ่าน Feedback Hub ไม่ค่อยได้ผล พร้อมแชร์ว่าเคยรายงานบั๊กที่เกี่ยวกับ SRWLOCK ไว้แล้ว
  • ผู้ใช้คนหนึ่งรำลึกว่าในอดีตเมื่อซื้อผลิตภัณฑ์ของ MS จะได้รับ support incident และหากพบว่าเป็นบั๊กจริงก็จะได้รับเงินคืนสำหรับ incident นั้น เขากล่าวว่านี่เป็นระบบที่ดี ทั้งมีประโยชน์ต่อผู้พัฒนาและให้ฟีดแบ็กแก่ MS เพื่อค้นหาปัญหาจริงและปรับปรุงเอกสาร พร้อมตั้งคำถามว่าโปรแกรมนี้ยังมีอยู่หรือไม่

    • ผู้ใช้คนหนึ่งรำลึกถึง support incident ที่เคยแถมมากับผลิตภัณฑ์ของ MS และบอกว่าระบบนี้เป็นประโยชน์ทั้งต่อผู้พัฒนาและต่อ MS พร้อมสงสัยว่าปัจจุบันยังมีอยู่หรือไม่
  • ท้ายที่สุด ผู้ใช้คนหนึ่งแสดงความผิดหวังต่อความยากลำบากในการรายงานบั๊กของ Windows API

    • ผู้ใช้คนหนึ่งแสดงความผิดหวังต่อความยากของการรายงานบั๊กเกี่ยวกับ Windows API