2 ポイント 投稿者 GN⁺ 2024-03-04 | 1件のコメント | WhatsAppで共有

Windowsでのstd::shared_mutexのバグの可能性

  • あるソフトウェアチームが、Windowsでstd::shared_mutexに関連する予期しない動作を発見した。
  • この問題はMSVCでのみ発生し、MinGWや他のプラットフォームでは発生しない。
  • メインスレッドが排他的ロックを取得した後、複数の子スレッドが共有ロックを取得しようとすると、約1000回に1回の割合で「デッドロック」が発生する。
  • デッドロックが発生すると、正確に1つの子スレッドだけが共有ロックの取得に成功し、残りの子スレッドはlock_shared()で永遠にブロックされる。
  • この問題は、std::shared_mutexstd::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件のコメント

 
GN⁺ 2024-03-04
Hacker Newsの意見
  • あるユーザーは、なぜこの基本的な問題が長年発見されなかったのか不思議に思い、別のユーザーが示した説得力のある説明に言及している。共有モードでロックを試みるスレッドが、誤って排他モードでロックを取得してしまう場合があると指摘している。これは、共有モード取得スレッドと排他モード解放スレッドが同時に実行される際、原子的なビットテストおよびセット操作が重なって発生するためである。

    • あるユーザーは、共有ロックを取得している間に他のすべてのスレッドが共有ロック取得待ちになる再現コードがあり、その結果、いずれかのワーカースレッドが誤って排他ロックを取得するとデッドロックに陥る可能性があると説明している。一般的な使用例ではスレッド同士が互いに待たないため、デッドロックは発生しない。
  • 別のユーザーは、Reader/Writerロックで起こる微妙なバグに驚きはないと述べ、C++11とstd::shared_mutex以前にWin32ベースで内部実装を手がけた経験を共有している。共有ロックでひどい経験をしたため、絶対に必要でない限り避けるようにしていると明かしている。

    • あるユーザーは共有ロックに関する否定的な経験を共有し、std::shared_mutexの性能がstd::mutexに比べて著しく劣るため、データをダブルバッファリングしたほうが速いと述べている。
  • あるユーザーは、タイトルが誤解を招くと指摘し、実際のバグはWindows APIのslim reader/writer (SRW)ロックにあり、std::shared_mutexがSRWロックを使って実装されているため発見されたのだと説明している。Microsoftの社員が、このバグはWindows APIチームに内部的に提起されたと確認している。

    • あるユーザーは誤解を招くタイトルを指摘し、実際の問題はWindows APIのSRWロックにあり、Microsoftの社員がバグ提起を確認したことに言及している。
  • あるユーザーは、WINEの実装でも同じ問題が起きるのか気にしており、自分用にカスタマイズしたXP環境でもテストしたいと述べている。その環境ではSRW APIを含む複数の拡張を追加しており、SRW実装に基づくkeyed event APIでデッドロックを引き起こす競合状態を修正するためにカーネルへパッチを当てたという。

    • あるユーザーは、WINE実装でも同じ問題が起きるのか気にしており、自分のカスタムXP環境で試したいと述べている。この環境ではSRW APIを含む複数の拡張を追加し、SRW実装に基づくkeyed event APIでデッドロックを引き起こす競合状態を修正するためにカーネルへパッチを当てたという。
  • プログラムにバグがあることも指摘されている。非atomic変数とatomic変数を混在させてyield()のチェックループで使っており、非atomic変数は他スレッドに対するキャッシュ一貫性を保証しない。そのため、ループが永遠に回り続ける可能性がある。

    • あるユーザーはプログラムのバグを指摘し、非atomic変数とatomic変数を混在させて使うことで発生する問題を説明している。非atomic変数はキャッシュ一貫性を保証しないため、ループが無限に実行される可能性があると述べている。
  • あるユーザーは、このバグが2008年のVista版までさかのぼると述べ、これほど長い間誰にも発見されなかったことに驚きを示している。一般的なrwlockの利用では、共有ロックを取得できないランダムなケースは起こりうるが、デッドロックは発生しないと述べている。

    • あるユーザーは、このバグがVista版までさかのぼること、長期間発見されなかったことへの驚きを述べている。一般的なrwlockの利用ではデッドロックは起きないが、共有ロックを取得できないケースは発生しうると述べている。
  • あるユーザーは、Windows APIのバグ報告は非常に難しいと述べ、Feedback Hubで報告するよう案内されるものの、ほとんど効果がないと批判している。そのユーザーは、排他的所有者が所有権を解放した後、複数の読み取りスレッドが共有所有権を同時に取得しようとするとSRWLOCKがデッドロックする可能性があるというバグを報告した。

    • あるユーザーはWindows APIへのバグ報告が非常に難しいと述べ、Feedback Hub経由の報告は効果的ではないと批判している。SRWLOCKに関するバグを報告したことを共有している。
  • あるユーザーは、以前はMS製品を購入するとサポートインシデントが付いており、実際のバグを見つけるとそのサポートインシデントが返金されたことを思い出している。これは開発者にとって有益であり、MSにとっても実際の問題を発見し、ドキュメントを改善するためのフィードバックを得られる良い仕組みだったと述べている。このプログラムが今も存在するのか気にしている。

    • あるユーザーは、過去にMS製品に含まれていたサポートインシデントを回想し、この仕組みが開発者とMSの双方に有益だったと述べている。現在もこのプログラムが存在するのか気にしている。
  • 最後に、あるユーザーはWindows APIのバグ報告が難しいことに失望を表している。

    • あるユーザーは、Windows APIのバグ報告の難しさに対する失望を表している。