std:: signal
|
Definiert im Header
<csignal>
|
||
|
/* signal-handler */
*
signal
(
int
sig,
/* signal-handler */
*
handler
)
;
|
(1) | |
|
extern
"C"
using
/* signal-handler */
=
void
(
int
)
;
|
(2) | ( Nur zur Darstellung* ) |
Ändert die Behandlung des Signals sig . Abhängig von handler kann das Signal ignoriert, auf Standard gesetzt oder durch eine benutzerdefinierte Funktion behandelt werden.
Wenn ein Signalhandler auf eine Funktion gesetzt wird und ein Signal auftritt, ist implementierungsdefiniert, ob std :: signal ( sig, SIG_DFL ) unmittelbar vor dem Start des Signalhandlers ausgeführt wird. Zudem kann die Implementierung verhindern, dass eine implementierungsdefinierte Menge von Signalen auftritt, während der Signalhandler läuft.
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 führte
sigaction
ein, um diese implementierungsdefinierten Verhaltensweisen zu standardisieren)
Inhaltsverzeichnis |
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:
|
Rückgabewert
Vorheriger Signal-Handler bei Erfolg oder SIG_ERR bei Fehler (das Setzen eines Signal-Handlers kann auf einigen Implementierungen deaktiviert sein).
Signal-Handler
Die folgenden Einschränkungen gelten für die benutzerdefinierte Funktion, die als Signal-Handler installiert wird.
|
Wenn der Signalhandler NICHT als Ergebnis von std::abort oder std::raise (asynchrones Signal) aufgerufen wird, ist das Verhalten undefiniert, falls
|
(bis C++17) |
|
Eine einfache lockfreie atomare Operation ist ein Aufruf einer Funktion f aus <atomic> oder <stdatomic.h> (seit C++23) , sodass:
Das Verhalten ist undefiniert, wenn ein Signalhandler eine der folgenden Aktionen ausführt:
|
(seit C++17) |
Wenn die benutzerdefinierte Funktion bei der Behandlung von SIGFPE , SIGILL , SIGSEGV oder anderen implementierungsdefinierten Signalen, die eine Rechenausnahme spezifizieren, zurückkehrt, ist das Verhalten undefiniert.
Wenn der Signalhandler als Ergebnis von std::abort oder std::raise (synchrones Signal) aufgerufen wird, ist das Verhalten undefiniert, wenn der Signalhandler std::raise aufruft.
|
Beim Eintritt in den Signal-Handler ist der Zustand der Gleitkommaumgebung und die Werte aller Objekte nicht spezifiziert, außer für
Bei der Rückkehr von einem Signal-Handler ist der Wert jedes Objekts, das durch den Signal-Handler geändert wurde und nicht volatile std:: sig_atomic_t oder lock-free std::atomic ist, unbestimmt. |
(bis C++14) | ||
|
Ein Aufruf der Funktion
Wenn ein Signal-Handler als Ergebnis eines Aufrufs von
std::raise
ausgeführt wird (synchron), dann ist die Ausführung des Handlers
sequenced-after
dem Aufruf von
Zwei Zugriffe auf dasselbe Objekt vom Typ volatile std:: sig_atomic_t führen nicht zu einem Data Race, wenn beide im selben Thread auftreten, selbst wenn einer oder mehrere in einem Signal-Handler auftreten. Für jeden Signal-Handler-Aufruf können die Auswertungen, die durch den Thread durchgeführt werden, der einen Signal-Handler aufruft, in zwei Gruppen A und B unterteilt werden, sodass keine Auswertungen in B happen-before Auswertungen in A, und die Auswertungen solcher volatile std:: sig_atomic_t Objekte Werte annehmen, als ob alle Auswertungen in A happened-before der Ausführung des Signal-Handlers und die Ausführung des Signal-Handlers happened-before allen Auswertungen in B. |
(seit C++14) |
Hinweise
POSIX erfordert, dass
signal
thread-sicher ist, und
spezifiziert eine Liste von asynchron-signalsicheren Bibliotheksfunktionen
, die von jedem Signal-Handler aufgerufen werden können.
Signal-Handler sollten C-Linkage besitzen und im Allgemeinen nur die Funktionen aus dem gemeinsamen Subset von C und C++ verwenden. Allerdings erlauben gängige Implementierungen, dass eine Funktion mit C++-Linkage als Signal-Handler verwendet wird.
Beispiel
#include <csignal> #include <iostream> namespace { volatile std::sig_atomic_t gSignalStatus; } void signal_handler(int signal) { gSignalStatus = signal; } int main() { // Installiere einen 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
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]
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| LWG 3756 | C++17 | es war unklar, ob std::atomic_flag signal-sicher ist | es ist |
Siehe auch
|
führt den Signal-Handler für ein bestimmtes Signal aus
(Funktion) |
|
|
(C++11)
|
Barriere zwischen einem Thread und einem Signal-Handler, der im selben Thread ausgeführt wird
(Funktion) |
|
C-Dokumentation
für
signal
|
|