std::signal
| ヘッダ <csignal>
|
||
/*signal-handler*/* signal( int sig, /*signal-handler*/* handler );
|
で定義 (1) | |
extern "C" using /*signal-handler*/ = void(int);
|
(2) | (説明専用*) |
シグナル sig の処理方法を変更します。handler の値に応じて、シグナルを無視したり、デフォルトに設定したり、(*handler)(sig) として呼び出されるユーザー定義関数で処理したりできます。
シグナルハンドラが関数に設定されていてシグナルが発生した場合、std::signal(sig, SIG_DFL) がシグナルハンドラの開始直前に実行されるかどうかは処理系定義です。また、処理系はシグナルハンドラの実行中に、処理系定義の一部のシグナルセットが発生するのを防ぐことができます。
一部のシグナルについては、処理系はプログラムの起動時に std::signal(sig, SIG_IGN) を呼び出す場合があります。残りのシグナルについては、処理系は std::signal(sig, SIG_DFL) を呼び出さなければなりません。
(注: POSIX はこれらの処理系定義の動作を標準化するために sigaction を導入しました。)
引数
| sig | - | シグナルハンドラを設定するシグナル。処理系定義の値、または以下の値のいずれかを使用できます:
| ||||||
| handler | - | シグナルハンドラ。以下のいずれかでなければなりません:
|
戻り値
成功時は前のシグナルハンドラ、失敗時は 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まで) | ||
|
関数
シグナルハンドラが
std::raise
の呼び出しの結果として(同期的に)実行される場合、ハンドラの実行は
同じ volatile std:: sig_atomic_t 型のオブジェクトへの2つのアクセスは、両方が同じスレッドで発生する場合、1つ以上がシグナルハンドラ内で発生してもデータ競合を引き起こさない。 各シグナルハンドラの起動について、シグナルハンドラを呼び出すスレッドによって実行される評価は、グループAとBの2つに分割でき、Bの評価がAの評価に対して happen-before 関係を持たず、かつそのような volatile std:: sig_atomic_t オブジェクトの評価は、Aの全ての評価がシグナルハンドラの実行に対して happened-before であり、シグナルハンドラの実行がBの全ての評価に対して happened-before であるかのように値を取る。 |
(C++14以降) |
注記
POSIX は signal がスレッドセーフであることを要求し、任意のシグナルハンドラから呼び出しても安全な非同期シグナルセーフなライブラリ関数のリストを規定している。
シグナルハンドラは C リンケージを持ち、一般的には C と C++ の共通部分集合の機能のみを使用することが期待される。ただし、一般的な実装では C++ リンケージを持つ関数をシグナルハンドラとして使用できる場合がある。
例
#include <csignal> #include <iostream> namespace { volatile std::sig_atomic_t gSignalStatus; } void signal_handler(int signal) { gSignalStatus = signal; } int main() { // シグナルハンドラをインストール 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 シグナルハンドラ [support.signal]
- C++20 標準 (ISO/IEC 14882:2020):
-
- 17.13.5 シグナルハンドラ [support.signal]
- C++17規格 (ISO/IEC 14882:2017):
-
- 21.10.4 シグナルハンドラ [support.signal]
欠陥報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3756 | C++17 |
std::atomic_flagがシグナルセーフであるか不明確であった
|
シグナルセーフである |
関連項目
|
特定のシグナルに対するシグナルハンドラを実行する
(関数) |
|
|
(C++11)
|
同じスレッドで実行されるスレッドとシグナルハンドラ間のフェンス
(関数) |
|
Cドキュメント
for
signal
|
|