yohhoyの日記

技術的メモをしていきたい日記

signal関数プロトタイプ宣言

C++17以降のC++標準ライブラリ仕様では、signal関数のプロトタイプ宣言が読みやすく書き直されている。

C++17仕様

C++標準ライブラリ仕様としてプロトタイプ宣言が行われている。C++17 21.10.3より宣言を引用:

Header <csignal> synopsis

namespace std {
  // 21.10.4, signal handlers
  extern "C" using signal-handler = void(int); // exposition only
  signal-handler* signal(int sig, signal-handler* func);
}

The contents of the header <csignal> are the same as the C standard library header <signal.h>.

またC++標準において、シグナルハンドラ内で行っても良い Signal-safe 操作の定義がなされている。C++17 21.10.4/p3より引用:

An evaluation is signal-safe unless it includes one of the following:

  • a call to any standard library function, except for plain lock-free atomic operations and functions explicitly identified as signal-safe. [Note: This implicitly excludes the use of new and delete expressions that rely on a library-provided memory allocator. -- end note]
  • an access to an object with thread storage duration;
  • a dynamic_cast expression;
  • throwing of an exception;
  • control entering a try-block or function-try-block;
  • initialization of a variable with static storage duration requiring dynamic initialization (6.6.3, 9.7); or
  • waiting for the completion of the initialization of a variable with static storage duration (9.7).

A signal handler invocation has undefined behavior if it includes an evaluation that is not signal-safe.

C++03/11/14仕様

C++14以前の仕様では独自のプロトタイプ宣言を行わず、標準Cヘッダ<signal.h>を参照している。

シグナルハンドラ内からの(一部例外を除く)C++関数呼び出しは処理系定義(implementation-defined)とされ、Signal-safeに関する言及は存在しない。C++14 18.10/p10より一部引用:

The common subset of the C and C++ languages consists of all declarations, definitions, and expressions that may appear in a well formed C++ program and also in a conforming C program. A POF ("plain old function") is a function that uses only features from this common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use plain lock-free atomic operations. (snip) All signal handlers shall have C linkage. The behavior of any function other than a POF used as a signal handler in a C++ program is implementation-defined.228
脚注228) In particular, a signal handler using exception handling is very likely to have problems. Also, invoking std::exit may cause destruction of objects, including those of the standard library implementation, which, in general, yields undefined behavior in a signal handler (see 1.9).

C仕様

C17 7.14.1.1/p1より宣言を引用:

Synopsis

#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);

シグナルハンドラ内で許可される操作は、条件付きで明示的に列挙されている。C17 7.14.1.1/p4-5より一部引用:

4 If the signal occurs as the result of calling the abort or raise function, the signal handler shall not call the raise function.
5 If the signal occurs other than as the result of calling the abort or raise function, the behavior is undefined if the signal handler refers to any object with static or thread storage duration that is not a lock-free atomic object other than by assigning a value to an object declared as volatile sig_atomic_t, or the signal handler calls any function in the standard library other than (snip)

関連URL