Namespaces
Variants

std::signal

От ru.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)
 
 
Определён в заголовке <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 или (since C++11) volatile std:: sig_atomic_t .
(until C++17)

Простая операция с атомарным доступом без блокировок — это вызов функции f из <atomic> или <stdatomic.h> (since C++23) , такой что:

  • 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 является функцией не-членом, и для каждого аргумента-указателя на атомарный тип arg , переданного в f , std:: atomic_is_lock_free ( arg ) возвращает true .

Поведение не определено, если любой обработчик сигнала выполняет любое из следующего:

  • вызов любой библиотечной функции, за исключением простых операций с атомарным доступом без блокировок и следующих безопасных для сигналов функций (обратите внимание, в частности, что динамическое выделение памяти не является безопасным для сигналов):
  • доступ к объекту с продолжительностью хранения потока
  • выражение dynamic_cast
  • выражение throw
  • вход в try блок
  • инициализация статической переменной, которая выполняет динамическую нелокальную инициализацию (включая отложенную до первого ODR-использования)
  • ожидание завершения инициализации любой переменной со статической продолжительностью хранения из-за её параллельной инициализации другим потоком
(since C++17)

Если пользовательская функция возвращает управление при обработке SIGFPE , SIGILL , SIGSEGV или любого другого определяемого реализацией сигнала, указывающего на вычислительное исключение, поведение не определено.

Если обработчик сигнала вызывается в результате std::abort или std::raise (синхронный сигнал), поведение не определено, если обработчик сигнала вызывает std::raise .

При входе в обработчик сигнала состояние среды с плавающей запятой и значения всех объектов не определены, за исключением:

(since C++11)

При возврате из обработчика сигнала значение любого объекта, измененного обработчиком сигнала, который не является volatile std:: sig_atomic_t или lock-free std::atomic , является неопределенным.

(until 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.

(since C++14)

Примечания

POSIX требует, чтобы signal была потокобезопасной, и определяет список библиотечных функций, безопасных для асинхронных сигналов, которые могут вызываться из любого обработчика сигнала.

Обработчики сигналов должны иметь связывание C (C linkage) и, как правило, использовать только возможности общего подмножества языков 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 it was unclear whether std::atomic_flag is signal-safe it is

Смотрите также

запускает обработчик сигнала для определенного сигнала
(функция)
барьер между потоком и обработчиком сигнала, выполняемым в том же потоке
(функция)