Namespaces
Variants

std:: signal

From cppreference.net
Utilities library
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:
definiert Signaltypen
(Makrokonstante)
handler - der Signal-Handler. Dies muss einer der folgenden sein:
  • SIG_DFL Makro. Der Signal-Handler wird auf den Standard-Signal-Handler gesetzt.
  • SIG_IGN Makro. Das Signal wird ignoriert.
  • Ein Zeiger auf eine Funktion. Die Signatur der Funktion muss äquivalent zu Folgendem sein:
extern "C" void fun ( int sig ) ;


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

  • der Signalhandler eine beliebige Funktion innerhalb der Standardbibliothek aufruft, außer
  • std::abort
  • std::_Exit
  • std::quick_exit
  • std::signal mit dem ersten Argument als Nummer des aktuell behandelten Signals (asynchroner Handler kann sich selbst erneut registrieren, aber keine anderen Signale).
(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:

  • Aufruf einer beliebigen Bibliotheksfunktion, außer einfachen lockfreien atomaren Operationen und den folgenden signalsicheren Funktionen (beachten Sie insbesondere, dass dynamische Allokation nicht signalsicher ist):
  • Zugriff auf ein Objekt mit Thread-Speicherdauer
  • ein dynamic_cast Ausdruck
  • ein throw Ausdruck
  • Eintritt in einen try Block
  • Initialisierung einer statischen Variable, die dynamische Nicht-Lokal-Initialisierung durchführt (einschließlich verzögert bis zur ersten ODR-Nutzung)
  • Warten auf den Abschluss der Initialisierung einer beliebigen Variable mit statischer Speicherdauer aufgrund gleichzeitiger Initialisierung durch einen anderen Thread
(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

(seit C++11)

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 signal() synchronisiert mit jeder daraus resultierenden Ausführung des Signal-Handlers.

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 std::raise und sequenced-before der Rückkehr davon und läuft im selben Thread wie std::raise . Die Ausführung der Handler für andere Signale ist unsequenced in Bezug auf den Rest des Programms und läuft in einem nicht spezifizierten Thread.

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)
Barriere zwischen einem Thread und einem Signal-Handler, der im selben Thread ausgeführt wird
(Funktion)
C-Dokumentation für signal