2016-04-14 7 views

Antwort

2

Nr

Signal-Handler haben keine Ahnung davon, welchen Faden sie die Ausführung auf, so hat thread_local keine gültige Semantik dort. [Intro.multithread] p2:

Ein Signalbehandlungsroutine, die als Ergebnis eines Aufruf die raise Funktion ausgeführt wird, gehört zu dem gleichen Ausführungs-Thread wie der Aufruf der Funktion raise. Ansonsten ist nicht spezifiziert, welcher Ausführungs-Thread einen Signal-Handler-Aufruf enthält.

Ebenfalls relevant ist p23:

Zwei Aktionen sind potentiell konkurrierende wenn

  • sie von verschiedenen Threads ausgeführt werden, oder
  • sie sind unsequenced, und mindestens ein wird von einem Signalhandler durchgeführt.

Die Ausführung eines Programm enthält ein Daten Rennen wenn es zwei potentiell konkurrierenden widersprüchlichen Aktionen enthält, mindestens eines davon nicht atomar ist, und weder geschieht vor dem anderen, mit Ausnahme des Sonderfall für Handler Signal nachstehend beschrieben. Ein solches Datenrennen führt zu undefiniertem Verhalten.

(Der Sonderfall für Signal-Handler bezeichnet wird, um nur in Bezug auf die Art volatile sig_atomic_t und gilt hier nicht.)

Die zweite Kugel wegen betrifft [intro.execution] p6:

Wenn ein Signalhandler als Ergebnis eines Aufrufs der raise-Funktion ausgeführt wird, wird die Ausführung des Handlers nach dem Aufruf der raise-Funktion und vor ihrer Rückkehr sequenziert. [] Hinweis: Wenn ein Signal aus einem anderen Grund empfangen wird, ist die Ausführung des Signal-Handlers normalerweise in Bezug auf den Rest des Programms nicht sequentiell. - Endnote]

+0

Signalhandler sind durch [\ [support.runtime \]/10] (http://eel.is/c++draft/support.runtime#10) eingeschränkt. –

0

Diese Antwort kann einen Zusatz von ildjarn gegeben, um die Antwort in Betracht gezogen werden. Wenn streng genommen vom C++ 14-Standard gesprochen wird, führt die Verwendung von Daten mit thread_local-Speicher von einem Signal-Handler zu undefiniertem Verhalten.

Auf bestimmten Plattformen ist eine solche Verwendung jedoch zulässig. Zum Beispiel implementieren die meisten POSIX-Systeme threadlokalen Speicher unter Verwendung eines speziellen Datensegments, das pro Thread zugewiesen wird (wie der Stapel). Ausführliche Erläuterungen finden Sie unter this document. In diesem Fall ist der Zugriff auf lokale Thread-Daten async-sicher, da es keine Sperren enthält.

Die vom Signalhandler gelesenen oder geschriebenen Daten sind jedoch möglicherweise immer noch inkonsistent, wenn nicht nur auf Atomics zugegriffen wird oder der Zugriff durch Verwendung von std::atomic_signal_fence umzäunt wird. Der Grund dafür ist, dass der Compiler nun eine Idee hat, wenn ein Signal-Handler die Ausführung unterbrechen könnte und somit Lese- und Schreib-Befehle neu anordnen könnte. std::atomic_signal_fence verbietet diese Neuordnung und Umordnung durch die CPU ist kein Problem, da die Ausführung innerhalb des gleichen Threads geschieht und die CPU nur Befehle neu anordnen darf, wenn das Ergebnis (innerhalb des Threads) gleich ist, als ob die Anweisungen in der Reihenfolge ausgeführt worden wären .

Zusätzlich zu std :: atomic_signal_fence ist die Verwendung von Variablen vom Typ std :: atomic sicher, solange sie frei von Sperren sind (wie durch std :: is_lock_free angezeigt).

Unter Linux (und ich glaube die meisten anderen POSIX-Plattformen) hängt die Frage, ob ein Signal an einen bestimmten Thread gesendet wird, davon ab, wie dieses Signal erzeugt wird und die genaue Art des Signals. Beispielsweise werden SIGSEGV und SIGBUS immer an den Thread gesendet, der den Fehler verursacht hat, der zu dem Signal geführt hat. In diesem Fall kann die Verwendung von lokalem Thread-Speicher eine bequeme Möglichkeit sein, um sich von solchen Fehlern zu erholen. Es gibt jedoch keine Möglichkeit, dies zu tun, während der Code für alle Plattformen, die den C++ - Standard unterstützen, portabel ist.