std::signal

std::signal 在标题
(1) extern "C" using /*signal-handler*/ = void(int);
(2) (exposition only*) 更改信号 sig 的处理。根据 handler ,可以忽略该信号、将其设置为默认值或由用户定义的函数处理该信号。
当信号处理程序设置为函数并且发生信号时,实现定义 std::signal(sig, SIG_DFL) 是否在信号处理程序启动之前立即执行。此外,实现可以防止在信号处理程序运行时发生某些实现定义的信号集。
对于某些信号,实现可以在程序启动时调用 std::signal(sig, SIG_IGN) 。对于其余信号,实现必须调用 std::signal(sig, SIG_DFL) 。
(注意:POSIX 引入了 sigaction 来标准化这些实现定义的行为)
Parameters sig - 要设置信号处理程序的信号。它可以是实现定义的值或以下值之一: SIGABRTSIGFPESIGILLSIGINTSIGSEGVSIGTERM 定义信号类型 (macro constant)
handler - 信号处理程序。它必须是下列之一:
SIG_DFL 宏。信号处理程序设置为默认信号处理程序。
SIG_IGN 宏。该信号被忽略。
指向函数的指针。函数的签名必须与以下内容等效:
extern "C" void fun(int sig);
Return value 成功时使用前一个信号处理程序,失败时使用 SIG_ERR (在某些实现中可以禁用设置信号处理程序)。
Signal handler 作为信号处理程序安装的用户定义函数受到以下限制。
如果信号处理程序不是由于 std::abort 或 std::raise (异步信号)而调用的,则行为未定义,如果
信号处理程序调用标准库中的任何函数,但以下情况除外
std::abort
std::_Exit
std::quick_exit
std::signal 第一个参数是当前处理的信号编号(异步处理程序可以重新注册自身,但不能重新注册其他信号)。
信号处理程序引用任何存储持续时间为 static 且不是 std::atomic 或(自 C++11 起)挥发性 std::sig_atomic_t 的对象。
(until C++17)
A普通无锁原子操作是从
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 。
如果任何信号处理程序执行以下操作之一,则行为未定义:
调用任何 library 函数,除了普通的无锁原子操作和以下signal-safe函数(特别注意,动态分配不是信号安全的):
std::signal 第一个参数是当前处理的信号编号(信号处理程序可以重新注册自身,但不能重新注册其他信号)。
std::numeric_limits 的成员函数
std::_Exit
std::abort
std::quick_exit
std::initializer_list 的成员函数以及 std::begin 和 std::end 的 std::initializer_list 重载
型号
所有功能来自
std::memcpy 和 std::memmove
访问具有线程存储持续时间的对象
dynamic_cast 表达式
throw 表达式
进入 try 块,包括 function-try-block
初始化执行 dynamic non-local initialization 的 static 变量(包括延迟到第一次 ODR 使用)
等待任何存储持续时间为 static 的变量的初始化完成,因为另一个线程正在同时初始化它
(since C++17)
如果用户定义函数在处理 SIGFPE 、 SIGILL 、 SIGSEGV 或任何其他指定计算异常的实现定义信号时返回,则行为未定义。
如果由于 std::abort 或 std::raise (同步信号)而调用信号处理程序,则当信号处理程序调用 std::raise 时,行为未定义。
进入信号处理程序时, floating-point environment 的状态和所有对象的值均未指定,但以下情况除外:
挥发性 std::sig_atomic_t 类型的对象
无锁 std::atomic 类型的对象
通过 std::atomic_signal_fence 可见的副作用
(since C++11)
从信号处理程序返回时,由信号处理程序修改的任何非易失性 std::sig_atomic_t 或无锁 std::atomic 对象的值都是不确定的。
(until C++14)
对函数 signal() synchronizes-with 的调用会导致信号处理程序的调用。
如果由于调用 std::raise (同步)而执行信号处理程序,则处理程序的执行为sequenced-after调用 std::raise 和sequenced-before从中返回,并在与 std::raise 相同的线程上运行。其他信号的处理程序的执行是unsequenced相对于程序的其余部分并在未指定的线程上运行。
如果对同一 volatile std::sig_atomic_t 类型的同一对象的两次访问都发生在同一线程中,则不会导致数据争用,即使一个或多个访问发生在信号处理程序中。对于每个信号处理程序调用,调用信号处理程序的线程执行的评估可以分为两组 A 和 B,这样 B 中的评估就不会发生happen-before A 中的求值,以及此类易失性 std::sig_atomic_t 对象的求值都取值,就好像 A happened-before 中的所有求值、信号处理程序的执行以及信号处理程序的执行happened-beforeB 中的所有评估。
(since C++14)
Notes POSIX 要求 signal 是线程安全的,并且 specifies a list of async-signal-safe library functions 可以从任何信号处理程序调用。
信号处理程序预计具有 C linkage ,并且通常仅使用 C 和 C++ 的通用子集的功能。但是,通用实现允许将具有 C++ 链接的函数用作信号处理程序。
Example #include
#include
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';
} Possible output:
SignalValue: 0
Sending signal: 2
SignalValue: 2 References
C++23 标准 (ISO/IEC 14882:2023):
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]
Defect reports 以下行为改变缺陷报告追溯应用于先前发布的 C++ 标准。
DR Applied to 已发布的行为 Correct behavior
LWG 3756 C++17 尚不清楚 std::atomic_flag 是否具有信号安全 it is
See also raise 运行特定信号的信号处理程序 (function)
atomic_signal_fence
(C++11) 线程与在同一线程中执行的信号处理程序之间的隔离 (function)
C documentation 适用于 signal
© cppreference.com根据 Creative Commons Attribution-ShareAlike Unported License v3.0 授权。
https://en.cppreference.com/w/cpp/utility/program/signal