std::signal
| ヘッダ <csignal> で定義 |
||
| /* signal-handler */* signal( int sig, /* signal-handler */* handler ); |
(1) | |
| extern "C" using /* signal-handler */ = void(int); |
(2) | (説明用*) |
シグナル sig のハンドリングを変更します。 handler に応じて、シグナルは無視されるか、デフォルトに設定されるか、またはユーザー定義関数によって処理される可能性があります。
シグナルハンドラが関数に設定され、シグナルが発生した場合、シグナルハンドラの開始直前に std::signal(sig, SIG_DFL) が実行されるかどうかは実装定義です。また、実装は、シグナルハンドラが実行されている間、一部の実装定義されたシグナルの発生を防止することができます。
一部のシグナルについては、プログラムの起動時に実装によって std::signal(sig, SIG_IGN) が呼び出される場合があります。それ以外の場合は、実装は std::signal(sig, SIG_DFL) を呼び出す必要があります。
(注: POSIX は、これらの実装定義の動作を標準化するために sigaction を導入しました)
目次 |
[編集] パラメータ
| sig | - | シグナルハンドラを設定するシグナル。実装定義の値、または以下のいずれかの値になります。
| ||||||
| ハンドラ | - | シグナルハンドラ。以下のいずれかである必要があります。
|
[編集] 戻り値
成功した場合は以前のシグナルハンドラ、失敗した場合は SIG_ERR。 (一部の実装では、シグナルハンドラの設定が無効になっている場合があります)。
[編集] シグナルハンドラ
シグナルハンドラとしてインストールされたユーザー定義関数には、以下の制限が課せられます。
|
シグナルハンドラが std::abort または std::raise の結果として呼び出されない場合 (非同期シグナル)、以下の場合は未定義の動作となります。
|
(C++17まで) |
|
プレーンなロックフリーアトミック操作とは、<atomic>または <stdatomic.h>(C++23 以降) の関数 f の呼び出しであり、以下の条件を満たすものです。
シグナルハンドラが以下のいずれかを実行した場合、動作は未定義です。
|
(C++17以降) |
SIGFPE、SIGILL、SIGSEGV、または計算例外を指定するその他の実装定義シグナルを処理中にユーザー定義関数が復帰した場合、動作は未定義です。
std::abort または std::raise の結果としてシグナルハンドラが呼び出された場合 (同期シグナル)、シグナルハンドラが std::raise を呼び出した場合の動作は未定義です。
|
シグナルハンドラに入ると、浮動小数点環境の状態とすべてのオブジェクトの値は未指定ですが、以下は例外です。
シグナルハンドラから復帰すると、シグナルハンドラによって変更された、volatile std::sig_atomic_t またはロックフリー std::atomic でない任意のオブジェクトの値は不定です。 |
(C++14まで) | ||
|
関数 `signal()` の呼び出しは、結果として生じるシグナルハンドラの呼び出しと 同期します。 シグナルハンドラが std::raise の呼び出しによって実行された場合 (同期)、ハンドラの実行は volatile std::sig_atomic_t 型の同じオブジェクトへの 2 つのアクセスは、たとえ一方または両方がシグナルハンドラ内で発生する場合でも、同じスレッド内で発生する場合、データ競合を引き起こしません。各シグナルハンドラ呼び出しについて、シグナルハンドラを呼び出すスレッドによって実行される評価は、2 つのグループ A および B に分割でき、B の評価が A の評価の *前に発生する* ことはなく、そのような volatile std::sig_atomic_t オブジェクトの評価は、A のすべての評価がシグナルハンドラの実行の *前に発生した* かのように値を持ち、シグナルハンドラの実行は B のすべての評価の *前に発生した* かのように動作します。 |
(C++14以降) |
[編集] 注意
POSIX は `signal` がスレッドセーフであることを要求しており、任意のシグナルハンドラから呼び出し可能な、async-signal-safe なライブラリ関数のリストを指定しています。
シグナルハンドラは C リンケージを持つことが期待されており、一般的には C と C++ の共通部分からの機能のみを使用します。ただし、一般的な実装では、C++ リンケージを持つ関数をシグナルハンドラとして使用できます。
[編集] 例
#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'; }
実行結果の例
SignalValue: 0 Sending signal: 2 SignalValue: 2
[編集] 参照
- C++23標準 (ISO/IEC 14882:2024)
- 17.13.5 Signal handlers [support.signal]
- C++20 standard (ISO/IEC 14882:2020)
- 17.13.5 Signal handlers [support.signal]
- C++17 standard (ISO/IEC 14882:2017)
- 21.10.4 Signal handlers [support.signal]
[編集] 欠陥レポート
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3756 | C++17 | std::atomic_flag がシグナルセーフであるか不明瞭でした。 |
そうである |
[編集] 関連項目
| 特定のシグナルに対してシグナルハンドラを実行する (関数) | |
| (C++11) |
スレッドと、同じスレッドで実行されるシグナルハンドラとの間のフェンス (関数) |
| C ドキュメント (
signal) | |