Namespaces
Variants

std::signal

ja.cppreference.net より
 
 
ユーティリティライブラリ
言語サポート
型サポート (基本型、RTTI)
ライブラリ機能テストマクロ (C++20)
プログラムユーティリティ
可変長引数関数
コルーチンサポート (C++20)
契約サポート (C++26)
三方比較
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

汎用ユーティリティ
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)(C++20)(C++20)    
(C++20)
Swap と 型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
共通語彙型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
 
ヘッダ <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_DFL マクロ。シグナルハンドラはデフォルトのシグナルハンドラに設定されます。
  • SIG_IGN マクロ。シグナルは無視されます。
  • 関数へのポインタ。関数のシグネチャは以下のものと等価でなければなりません:
extern "C" void fun(int sig);

戻り値

成功時は前のシグナルハンドラ、失敗時は SIG_ERR を返す(一部の実装ではシグナルハンドラの設定が無効化されている場合がある)。

シグナルハンドラ

シグナルハンドラとしてインストールされるユーザー定義関数には以下の制限が課されます。

シグナルハンドラが std::abort または std::raise の結果として呼び出されない場合(非同期シグナル)、以下の場合の動作は未定義です:

  • シグナルハンドラが標準ライブラリ内の任意の関数を呼び出す場合、ただし以下を除く:
  • std::abort
  • std::_Exit
  • std::quick_exit
  • std::signal で、第一引数が現在処理中のシグナル番号である場合(非同期ハンドラは自身を再登録できるが、他のシグナルは登録できない)。
  • シグナルハンドラが、静的記憶域期間を持つオブジェクトを参照する場合で、そのオブジェクトが std::atomic または (C++11以降) volatile std:: sig_atomic_t でない場合。
(C++17まで)

プレーンロックフリーアトミック操作 とは、 <atomic> または <stdatomic.h> (C++23以降) からの関数 f の呼び出しであり、以下のいずれかの条件を満たすもの:

  • f が関数 std::atomic_is_lock_free である場合、
  • f がメンバ関数 is_lock_free である場合(例: std::atomic::is_lock_free() )、
  • f が std::atomic_flag の非静的メンバ関数である場合、
  • f が非メンバ関数であり、 f の第一引数の型が cv std:: atomic_flag * である場合、
  • f がオブジェクト obj に対して呼び出される非静的メンバ関数であり、 obj. is_lock_free ( ) が true を返す場合、または
  • f が非メンバ関数であり、 f に渡されるすべてのアトミックへのポインタ引数 arg に対して、 std:: atomic_is_lock_free ( arg ) が true を返す場合。

シグナルハンドラが以下のいずれかを実行する場合、動作は未定義です:

  • プレーンロックフリーアトミック操作および以下の シグナルセーフ 関数を除く、任意のライブラリ関数の呼び出し(特に、動的確保はシグナルセーフでないことに注意):
  • スレッド記憶域期間を持つオブジェクトへのアクセス
  • dynamic_cast 式
  • throw 式
  • try ブロック へのエントリ
  • 動的非ローカル初期化(最初のODR使用まで遅延されるものを含む)を実行する静的変数の初期化
  • 別のスレッドによる並行初期化による静的記憶域期間を持つ任意の変数の初期化完了の待機
(C++17以降)

ユーザー定義関数が SIGFPE 、 SIGILL 、 SIGSEGV または計算例外を指定するその他の実装定義シグナルを処理中に戻った場合、動作は未定義です。

シグナルハンドラが std::abort または std::raise (同期シグナル)の結果として呼び出された場合、シグナルハンドラが std::raise を呼び出すと動作は未定義です。

シグナルハンドラのエントリ時点では、 浮動小数点環境 の状態と全てのオブジェクトの値は未規定である。ただし以下を除く:

(C++11以降)

シグナルハンドラからのリターン時、シグナルハンドラによって変更されたオブジェクトの値で、 volatile std:: sig_atomic_t またはロックフリーな std::atomic でないものは不定である。

(C++14まで)

関数 signal() の呼び出しは、結果として生じるシグナルハンドラの起動と synchronizes-with 関係を持つ。

シグナルハンドラが std::raise の呼び出しの結果として(同期的に)実行される場合、ハンドラの実行は std::raise の呼び出しに対して sequenced-after であり、そのリターンに対して sequenced-before であり、 std::raise と同じスレッド上で実行される。 他のシグナルのハンドラの実行は、プログラムの残りの部分に対して unsequenced であり、未規定のスレッド上で実行される。

同じ 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がシグナルセーフであるか不明確であった シグナルセーフである

関連項目

特定のシグナルに対するシグナルハンドラを実行する
(関数)
同じスレッドで実行されるスレッドとシグナルハンドラ間のフェンス
(関数)