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 или (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 linkage и, как правило, используют только возможности из общего подмножества C и C++. Однако распространённые реализации позволяют использовать функцию с C++ linkage в качестве обработчика сигнала.

Пример

#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

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

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