Möglicher Bug von std::shared_mutex unter Windows
- Ein Softwareteam hat unter Windows ein unerwartetes Verhalten im Zusammenhang mit
std::shared_mutex entdeckt.
- Das Problem tritt nur mit MSVC auf und nicht mit MinGW oder auf anderen Plattformen.
- Wenn der Haupt-Thread eine exklusive Sperre erwirbt und danach mehrere Child-Threads versuchen, eine gemeinsame Sperre zu erlangen, kommt es in etwa 1 von 1000 Fällen zu einem „Deadlock“.
- Tritt der Deadlock auf, kann genau 1 Child-Thread die gemeinsame Sperre erfolgreich erwerben, während die übrigen Child-Threads in
lock_shared() dauerhaft blockiert bleiben.
- Das Problem wurde bei
std::shared_mutex, std::shared_lock/std::unique_lock sowie bei direkten Aufrufen von SRW-Funktionen beobachtet.
Codebeispiel und Reproduktion des Bugs
- Es wurde ein einfaches Codebeispiel bereitgestellt, mit dem sich das Problem reproduzieren lässt.
- Der Code wiederholt den Ablauf, bei dem der Haupt-Thread eine exklusive Sperre erwirbt und mehrere Child-Threads anschließend eine gemeinsame Sperre erwerben und wieder freigeben.
- Dieser Code zeigt den Bug im Zusammenhang mit
std::shared_mutex nur in der Windows-MSVC-Implementierung.
Einschätzung von Experten
- Ein STL-Entwickler erwähnte, dass es sich offenbar um einen Bug in der Windows-API handelt.
- Es gab eine Diskussion über die richtigen Schritte zur Meldung des Bugs, und der STL-Entwickler hat ihn intern gemeldet.
- Andere Nutzer haben das Problem genauer untersucht und dazu beigetragen, den Bug auf eine bestimmte Schwachstelle in der SRWLock-Implementierung einzugrenzen.
Meinung von GN⁺
- Dieser Artikel liefert besonders für C++-Entwickler wichtige Informationen, da ein potenzieller Bug in
std::shared_mutex die Synchronisierungsmechanismen von Multithreading-Anwendungen beeinträchtigen kann.
- Falls der Bug bestätigt wird, könnte das das Vertrauen in die Implementierung der C++-Standardbibliothek beeinflussen. Entwickler sollten sich solcher Probleme bewusst sein und gegebenenfalls alternative Synchronisationsmechanismen in Betracht ziehen.
- Das Problem kann besonders in Hochleistungs- oder Echtzeitsystemen relevant sein, da Deadlocks dort schwerwiegende Folgen haben können.
- Vor dem Einsatz dieser Technik sollten Entwickler umfangreiche Tests für die jeweilige Plattform und den verwendeten Compiler durchführen, um sicherzustellen, dass keine Bugs dieser Art vorhanden sind.
- Um solche Probleme zu umgehen, können Entwickler alternative Synchronisationsbibliotheken wie die Boost-Bibliothek in Betracht ziehen. Da Boost breit getestet ist und auf vielen Plattformen eingesetzt wird, kann es eine stabile Alternative für solche Probleme bieten.
1 Kommentare
Hacker-News-Kommentare
Ein Nutzer fragt sich, warum ein so grundlegendes Problem so lange unentdeckt blieb, und verweist auf eine überzeugende Antwort eines anderen Nutzers. Er weist darauf hin, dass ein Thread, der versucht, die Sperre im Shared-Modus zu erwerben, versehentlich eine exklusive Sperre erhalten kann. Das geschieht durch eine Überlappung atomarer Bit-Test-und-Set-Operationen, wenn ein Thread zum Erwerb im Shared-Modus und ein Thread zur Freigabe im exklusiven Modus gleichzeitig laufen.
Ein anderer Nutzer sagt, ihn überraschten subtile Bugs bei Reader/Writer-Sperren nicht, und teilt seine Erfahrung mit einer internen Win32-basierten Implementierung aus der Zeit vor C++11 und
std::shared_mutex. Wegen schlechter Erfahrungen mit Shared-Sperren versuche er, sie zu vermeiden, sofern sie nicht absolut notwendig seien.Ein Nutzer weist darauf hin, dass der Titel irreführend sei, und erklärt, dass der eigentliche Bug in den slim reader/writer (SRW)-Sperren der Windows API liege und nur deshalb über
std::shared_mutexentdeckt wurde, weil dieses mit SRW-Sperren implementiert ist. Ein Microsoft-Mitarbeiter bestätigt, dass der Bug intern an das Windows-API-Team weitergegeben wurde.Ein Nutzer fragt sich, ob dasselbe Problem auch in der Implementierung von WINE auftritt, und sagt, er wolle es auch auf seiner angepassten XP-Installation testen. Dort habe er mehrere Erweiterungen einschließlich der SRW-API hinzugefügt und den Kernel gepatcht, um eine Race Condition zu beheben, die im auf der SRW-Implementierung basierenden Keyed-Event-API zu Deadlocks führte.
Es wird darauf hingewiesen, dass das Programm einen Bug hat. Es mischt nicht-atomare und atomare Variablen und verwendet sie in der Prüfschleife mit
yield(), wobei nicht-atomare Variablen keine Cache-Kohärenz gegenüber anderen Threads garantieren. Dadurch kann die Schleife unendlich weiterlaufen.Ein Nutzer sagt, der Bug reiche bis zur Vista-Version von 2008 zurück, und zeigt sich erstaunt, dass ihn über so lange Zeit niemand entdeckt habe. Er erwähnt, dass bei normaler rwlock-Nutzung zufällige Fälle auftreten können, in denen eine Shared-Sperre nicht erworben werden kann, ohne dass es zu einem Deadlock kommt.
Ein Nutzer sagt, es sei sehr schwierig, Bugs in der Windows API zu melden, und kritisiert, dass man zwar an den Feedback Hub verwiesen werde, dies aber kaum wirksam sei. Er berichtet, einen Bug gemeldet zu haben, bei dem
SRWLOCKin einen Deadlock geraten kann, wenn mehrere Lese-Threads nach der Freigabe durch den exklusiven Besitzer gleichzeitig versuchen, Shared-Besitz zu erwerben.Ein Nutzer erinnert sich daran, dass man früher beim Kauf von MS-Produkten Supportfälle erhielt und dass ein Supportfall erstattet wurde, wenn man einen echten Bug fand. Er sagt, das sei für Entwickler nützlich gewesen und auch für MS ein gutes System, weil es Feedback zu realen Problemen und zur Verbesserung der Dokumentation geliefert habe. Er fragt sich, ob es dieses Programm noch gibt.
Abschließend äußert ein Nutzer seine Enttäuschung darüber, wie schwierig es ist, Bugs in der Windows API zu melden.