Windowsでのstd::shared_mutexのバグの可能性
- あるソフトウェアチームが、Windowsで
std::shared_mutexに関連する予期しない動作を発見した。
- この問題はMSVCでのみ発生し、MinGWや他のプラットフォームでは発生しない。
- メインスレッドが排他的ロックを取得した後、複数の子スレッドが共有ロックを取得しようとすると、約1000回に1回の割合で「デッドロック」が発生する。
- デッドロックが発生すると、正確に1つの子スレッドだけが共有ロックの取得に成功し、残りの子スレッドは
lock_shared()で永遠にブロックされる。
- この問題は、
std::shared_mutex、std::shared_lock/std::unique_lock、またはSRW関数を直接呼び出す場合に観測される。
コード例とバグの再現
- 問題を再現できるシンプルなコードが提供されている。
- コードは、メインスレッドが排他的ロックを取得し、複数の子スレッドが共有ロックを取得した後でそれを解放する処理を繰り返す。
- このコードは、WindowsのMSVC実装でのみ
std::shared_mutexに関連するバグを示す。
専門家の見解
- STL開発者は、この問題はWindows APIのバグに見えると言及している。
- バグを報告するための適切な手順について議論があり、STL開発者が内部的にバグを報告した。
- 他のユーザーもこの問題を詳しく調査し、SRWLock実装の特定のバグを絞り込むことに貢献した。
GN⁺の見解
- この記事は、特にC++開発者にとって重要な情報を提供している。
std::shared_mutexの潜在的なバグは、マルチスレッドアプリケーションの同期メカニズムに影響を与える可能性があるためだ。
- バグが確認されれば、C++標準ライブラリの実装に対する信頼性にも影響する可能性がある。開発者はこうした問題を認識し、代替の同期メカニズムを検討する必要があるかもしれない。
- この問題は、特に高性能またはリアルタイムシステムで重要になる可能性がある。そうしたシステムでは、デッドロックが致命的な結果を招く可能性があるためだ。
- この技術を導入する前に、開発者は対象プラットフォームとコンパイラに対して広範なテストを実施し、この種のバグがないことを確認すべきである。
- この問題に対処するため、開発者はBoostライブラリのような代替の同期ライブラリを検討できる。Boostは広範にテストされ、多くのプラットフォームで使われているため、この種の問題に対する安定した代替手段を提供できる。
1件のコメント
Hacker Newsの意見
あるユーザーは、なぜこの基本的な問題が長年発見されなかったのか不思議に思い、別のユーザーが示した説得力のある説明に言及している。共有モードでロックを試みるスレッドが、誤って排他モードでロックを取得してしまう場合があると指摘している。これは、共有モード取得スレッドと排他モード解放スレッドが同時に実行される際、原子的なビットテストおよびセット操作が重なって発生するためである。
別のユーザーは、Reader/Writerロックで起こる微妙なバグに驚きはないと述べ、C++11と
std::shared_mutex以前にWin32ベースで内部実装を手がけた経験を共有している。共有ロックでひどい経験をしたため、絶対に必要でない限り避けるようにしていると明かしている。あるユーザーは、タイトルが誤解を招くと指摘し、実際のバグはWindows APIのslim reader/writer (SRW)ロックにあり、
std::shared_mutexがSRWロックを使って実装されているため発見されたのだと説明している。Microsoftの社員が、このバグはWindows APIチームに内部的に提起されたと確認している。あるユーザーは、WINEの実装でも同じ問題が起きるのか気にしており、自分用にカスタマイズしたXP環境でもテストしたいと述べている。その環境ではSRW APIを含む複数の拡張を追加しており、SRW実装に基づくkeyed event APIでデッドロックを引き起こす競合状態を修正するためにカーネルへパッチを当てたという。
プログラムにバグがあることも指摘されている。非atomic変数とatomic変数を混在させて
yield()のチェックループで使っており、非atomic変数は他スレッドに対するキャッシュ一貫性を保証しない。そのため、ループが永遠に回り続ける可能性がある。あるユーザーは、このバグが2008年のVista版までさかのぼると述べ、これほど長い間誰にも発見されなかったことに驚きを示している。一般的なrwlockの利用では、共有ロックを取得できないランダムなケースは起こりうるが、デッドロックは発生しないと述べている。
あるユーザーは、Windows APIのバグ報告は非常に難しいと述べ、Feedback Hubで報告するよう案内されるものの、ほとんど効果がないと批判している。そのユーザーは、排他的所有者が所有権を解放した後、複数の読み取りスレッドが共有所有権を同時に取得しようとするとSRWLOCKがデッドロックする可能性があるというバグを報告した。
あるユーザーは、以前はMS製品を購入するとサポートインシデントが付いており、実際のバグを見つけるとそのサポートインシデントが返金されたことを思い出している。これは開発者にとって有益であり、MSにとっても実際の問題を発見し、ドキュメントを改善するためのフィードバックを得られる良い仕組みだったと述べている。このプログラムが今も存在するのか気にしている。
最後に、あるユーザーはWindows APIのバグ報告が難しいことに失望を表している。