命名空间
变体
操作

std::signal

来自 cppreference.com
< cpp‎ | utility‎ | program
 
 
实用程序库
语言支持
类型支持 (基本类型,RTTI)
库功能测试宏 (C++20)
动态内存管理
程序实用程序
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三方比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用实用程序
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
通用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
基本字符串转换
(C++17)
(C++17)

 
 
定义在头文件 <csignal>
/* 信号处理程序 */* signal( int sig, /* 信号处理程序 */* handler );
(1)
extern "C" using /* 信号处理程序 */ = 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::abortstd::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,使得

如果任何信号处理程序执行以下操作,则行为未定义

  • 调用任何库函数,除了纯无锁原子操作和以下信号安全函数(请注意,特别是动态分配不是信号安全的)
  • 访问具有线程存储期的对象
  • 一个 dynamic_cast 表达式
  • 一个 throw 表达式
  • 进入 try
  • 初始化执行 动态非局部初始化(包括延迟到第一次 ODR 使用)的静态变量
  • 等待另一个线程并发初始化的任何具有静态存储期的变量的初始化完成
(自 C++17 起)

如果用户定义的函数在处理 SIGFPESIGILLSIGSEGV 或任何其他指定计算异常的实现定义信号时返回,则行为未定义。

如果信号处理程序是由于 std::abortstd::raise(同步信号)调用而被调用,则如果信号处理程序调用 std::raise,则行为未定义。

进入信号处理程序时,浮点环境 的状态以及所有对象的取值都是不确定的,除了

(自 C++11 起)

从信号处理程序返回时,由信号处理程序修改的任何对象的取值都是不确定的,除非该对象是 volatile std::sig_atomic_t 或无锁 std::atomic

(直到 C++14)

对函数 signal() 的调用 同步于任何由此产生的信号处理程序调用。

如果信号处理程序是由于调用 std::raise(同步)而执行的,则处理程序的执行顺序在std::raise 调用之后,并且顺序在从其返回之前,并且在与 std::raise 相同的线程上运行。其他信号处理程序的执行与程序的其余部分无序,并且在未指定的线程上运行。

对类型为 volatile std::sig_atomic_t 的同一个对象的两次访问不会导致数据竞争,即使这两次访问都在同一个线程中发生,即使其中一次或多次访问发生在信号处理程序中。对于每个信号处理程序调用,调用信号处理程序的线程执行的计算可以分为两组 A 和 B,这样 B 中的任何计算都不会发生在 A 中的计算之前,并且对这些 volatile std::sig_atomic_t 对象的计算取值就像 A 中的所有计算都发生在信号处理程序执行之前,并且信号处理程序的执行发生在 B 中所有计算之前一样。

(自 C++14 起)

[edit] Notes

POSIX 要求 signal 是线程安全的,并且 指定了可以从任何信号处理程序调用的异步信号安全库函数列表

预期信号处理程序具有 C 链接,并且通常只使用 C 和 C++ 的公共子集中的功能。但是,常见的实现允许将具有 C++ 链接的函数用作信号处理程序。

[edit] Example

#include <csignal>
#include <iostream>
 
namespace
{
    volatile std::sig_atomic_t gSignalStatus;
}
 
void signal_handler(int signal)
{
    gSignalStatus = signal;
}
 
int main()
{
    // Install a signal handler
    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

[edit] References

  • 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]

[edit] Defect reports

以下更改行为的缺陷报告被追溯应用于以前发布的 C++ 标准。

DR 应用于 已发布的行为 正确行为
LWG 3756 C++17 不清楚 std::atomic_flag 是否是信号安全的 它是

[edit] See also

运行特定信号的信号处理程序
(function) [edit]
在同一个线程中执行的线程和信号处理程序之间的栅栏
(function) [edit]
C 文档 for signal