2 Punkte von GN⁺ 2024-03-04 | 1 Kommentare | Auf WhatsApp teilen

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

 
GN⁺ 2024-03-04
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 Nutzer erklärt, dass es Reproduktionscode gibt, bei dem während des Erwerbs einer Shared-Sperre alle anderen Threads darauf warten, selbst Shared-Sperren zu erwerben; dadurch kann ein Deadlock entstehen, wenn ein Worker-Thread versehentlich eine exklusive Sperre erhält. In üblichen Anwendungsfällen warten Threads jedoch nicht aufeinander, daher tritt kein Deadlock auf.
  • 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 schildert negative Erfahrungen mit Shared-Sperren und erwähnt, dass die Performance von std::shared_mutex im Vergleich zu std::mutex deutlich schlechter sei, sodass Double Buffering schneller sei.
  • 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_mutex entdeckt 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 bemerkt, dass der Titel irreführend sei, da das eigentliche Problem in den SRW-Sperren der Windows API liege, und erwähnt, dass ein Microsoft-Mitarbeiter bestätigt habe, dass der Bug gemeldet 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.

    • Ein Nutzer fragt sich, ob dasselbe Problem auch in der WINE-Implementierung auftritt, und sagt, er wolle es auf seiner angepassten XP-Installation testen. In dieser Installation 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 weist auf den Bug im Programm hin und erklärt das Problem, das durch die Mischung aus nicht-atomaren und atomaren Variablen entsteht. Nicht-atomare Variablen garantieren keine Cache-Kohärenz, weshalb die Schleife endlos laufen kann.
  • 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, der Bug reiche bis zur Vista-Version zurück, und zeigt sich erstaunt, dass er so lange unentdeckt blieb. Bei normaler rwlock-Nutzung komme es zwar nicht zu Deadlocks, aber es könne Fälle geben, in denen eine Shared-Sperre nicht erworben werden kann.
  • 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 SRWLOCK in einen Deadlock geraten kann, wenn mehrere Lese-Threads nach der Freigabe durch den exklusiven Besitzer gleichzeitig versuchen, Shared-Besitz zu erwerben.

    • Ein Nutzer sagt, das Melden von Bugs in der Windows API sei sehr schwierig, und kritisiert, dass Meldungen über den Feedback Hub nicht effektiv seien. Er teilt mit, dass er einen Bug im Zusammenhang mit SRWLOCK gemeldet habe.
  • 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.

    • Ein Nutzer erinnert sich an die früher in MS-Produkten enthaltenen Supportfälle und sagt, dieses System sei sowohl für Entwickler als auch für MS nützlich gewesen. Er fragt sich, ob es dieses Programm heute noch gibt.
  • Abschließend äußert ein Nutzer seine Enttäuschung darüber, wie schwierig es ist, Bugs in der Windows API zu melden.

    • Ein Nutzer äußert seine Enttäuschung über die Schwierigkeit, Bugs in der Windows API zu melden.