std::signal
| Definiert in Header <csignal> |
||
| /* Signal-Handler */* signal( int sig, /* Signal-Handler */* handler ); |
(1) | |
| extern "C" using /* Signal-Handler */ = void(int); |
(2) | (nur Exposition*) |
Ändert die Behandlung des Signals sig. Abhängig von handler kann das Signal ignoriert, auf den Standardwert gesetzt oder von einer benutzerdefinierten Funktion behandelt werden.
Wenn der Signal-Handler auf eine Funktion gesetzt wird und ein Signal auftritt, ist es implementierungsabhängig, ob std::signal(sig, SIG_DFL) unmittelbar vor Beginn des Signal-Handlers ausgeführt wird. Außerdem kann die Implementierung einige implementierungsdefinierte Sätze von Signalen daran hindern, während der Ausführung des Signal-Handlers aufzutreten.
Für einige der Signale kann die Implementierung beim Programmstart std::signal(sig, SIG_IGN) aufrufen. Für den Rest muss die Implementierung std::signal(sig, SIG_DFL) aufrufen.
(Hinweis: POSIX hat sigaction eingeführt, um diese implementierungsabhängigen Verhaltensweisen zu standardisieren)
Inhalt |
[edit] Parameter
| sig | - | das Signal, für das der Signal-Handler gesetzt werden soll. Es kann ein implementierungsdefinierter Wert oder einer der folgenden Werte sein
| ||||||
| handler | - | der Signal-Handler. Dies muss einer der folgenden sein
|
[edit] Rückgabewert
Vorheriger Signal-Handler bei Erfolg oder SIG_ERR bei Fehler (das Setzen eines Signal-Handlers kann auf einigen Implementierungen deaktiviert sein).
[edit] Signal-Handler
Die folgenden Einschränkungen gelten für die benutzerdefinierte Funktion, die als Signal-Handler installiert wird.
|
Wenn der Signal-Handler NICHT als Ergebnis von std::abort oder std::raise (asynchrones Signal) aufgerufen wird, ist das Verhalten undefiniert, wenn
|
(bis C++17) |
|
Ein einfacher sperrfreier atomarer Vorgang ist ein Aufruf einer Funktion f aus <atomic> oder <stdatomic.h>(seit C++23), so dass
Das Verhalten ist undefiniert, wenn ein Signal-Handler eine der folgenden Aktionen ausführt:
|
(seit C++17) |
Wenn die benutzerdefinierte Funktion bei der Behandlung von SIGFPE, SIGILL, SIGSEGV oder einem anderen implementierungsdefinierten Signal, das eine rechnerische Ausnahme spezifiziert, zurückkehrt, ist das Verhalten undefiniert.
Wenn der Signal-Handler als Ergebnis eines Aufrufs von std::abort oder std::raise (synchrones Signal) aufgerufen wird, ist das Verhalten undefiniert, wenn der Signal-Handler std::raise aufruft.
|
Beim Eintritt in den Signal-Handler ist der Zustand der Gleitkommaumgebung und die Werte aller Objekte undefiniert, außer
Beim Rückkehren aus einem Signal-Handler sind die Werte von Objekten, die vom Signal-Handler geändert wurden und keine volatile std::sig_atomic_t oder sperrfreien std::atomic-Typen sind, unbestimmt. |
(bis C++14) | ||
|
Ein Aufruf der Funktion Wenn ein Signal-Handler als Ergebnis eines Aufrufs von std::raise (synchron) ausgeführt wird, dann ist die Ausführung des Handlers *sequenziert nach* dem Aufruf von Zwei Zugriffe auf dasselbe Objekt vom Typ volatile std::sig_atomic_t führen nicht zu einem Datenrennen, wenn beide im selben Thread auftreten, selbst wenn einer oder mehrere in einem Signal-Handler auftreten. Für jede Ausführung eines Signal-Handlers können die Auswertungen, die vom aufrufenden Thread durchgeführt werden, in zwei Gruppen A und B unterteilt werden, so dass keine Auswertungen in B *vor* Auswertungen in A geschehen, und die Auswertungen solcher volatile std::sig_atomic_t-Objekte Werte so erhalten, als ob alle Auswertungen in A *vor* der Ausführung des Signal-Handlers geschehen wären und die Ausführung des Signal-Handlers *vor* allen Auswertungen in B geschehen wäre. |
(seit C++14) |
[edit] Hinweise
POSIX verlangt, dass signal Thread-sicher ist, und spezifiziert eine Liste von asynchron-signal-sicheren Bibliotheksfunktionen, die von jedem Signal-Handler aufgerufen werden dürfen.
Signal-Handler sollen eine C-Verknüpfung haben und im Allgemeinen nur die Funktionen aus der gemeinsamen Teilmenge von C und C++ verwenden. Übliche Implementierungen erlauben jedoch die Verwendung einer Funktion mit C++-Verknüpfung als Signal-Handler.
[edit] Beispiel
#include <csignal> #include <iostream> namespace { volatile std::sig_atomic_t gSignalStatus; } void signal_handler(int signal) { gSignalStatus = signal; } int main() { // Install a signal handler std::signal(SIGINT, signal_handler); std::cout << "SignalValue: " << gSignalStatus << '\n'; std::cout << "Sending signal: " << SIGINT << '\n'; std::raise(SIGINT); std::cout << "SignalValue: " << gSignalStatus << '\n'; }
Mögliche Ausgabe
SignalValue: 0 Sending signal: 2 SignalValue: 2
[edit] Referenzen
- C++23 Standard (ISO/IEC 14882:2024)
- 17.13.5 Signal-Handler [support.signal]
- C++20 Standard (ISO/IEC 14882:2020)
- 17.13.5 Signal-Handler [support.signal]
- C++17 Standard (ISO/IEC 14882:2017)
- 21.10.4 Signal-Handler [support.signal]
[edit] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 3756 | C++17 | es war unklar, ob std::atomic_flag signal-sicher ist | sie ist |
[edit] Siehe auch
| führt den Signal-Handler für ein bestimmtes Signal aus (funktion) | |
| (C++11) |
Fence zwischen einem Thread und einem Signal-Handler, der im selben Thread ausgeführt wird (Funktion) |
| C-Dokumentation für signal
| |