Namespaces
Variants

std:: signal

From cppreference.net
Utilities library
定義済みヘッダー <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 - シグナルハンドラを設定するシグナル。実装定義の値または以下のいずれかの値を指定できます:
シグナルタイプを定義する
(マクロ定数)
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 がシグナルセーフであるか不明確であった シグナルセーフである

関連項目

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