Spec-Zone.ru › C++

std::signal

Определено в заголовке <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 - сигнал, для которого нужно задать обработчик. Может быть определенным реализацией значением или одним из следующих значений:
SIGABRTSIGFPESIGILLSIGINTSIGSEGVSIGTERM
определяет типы сигналов
(макро-константа)
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 или (с C++11)volatile std::sig_atomic_t.
(до C++17)

Простая атомарная операция без блокировок — вызов функции f из <atomic> или <stdatomic.h>(с 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.

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

  • вызов любой функции библиотеки, за исключением простых атомарных операций без блокировок и следующих функций, безопасных для сигналов (обратите внимание, что динамическое выделение памяти не безопасно для сигналов):
    • std::signal с первым аргументом, являющимся номером обрабатываемого в данный момент сигнала (обработчик сигнала может перерегистрировать себя, но не другие сигналы).
    • члены-функции std::numeric_limits
    • std::_Exit
    • std::abort
    • std::quick_exit
    • Члены-функции std::initializer_list и перегрузки std::initializer_list функций std::begin и std::end
    • std::forward, std::move, std::move_if_noexcept
    • Все функции из <type_traits>
    • std::memcpy и std::memmove
  • доступ к объекту со стековой продолжительностью жизни потока
  • выражение dynamic_cast
  • выражение throw
  • вход в блок try, включая функциональный try-блок
  • инициализация статической переменной, которая выполняет динамическую инициализацию вне локальной области (включая отложенную до первого использования ODR)
  • ожидание завершения инициализации любой переменной со статической продолжительностью жизни из-за другого потока, который в данный момент инициализирует её
(с C++17)

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

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

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

  • объектов типа volatile std::sig_atomic_t
  • объектов с типом, не требующим блокировок std::atomic
  • побочных эффектов, сделанных видимыми через std::atomic_signal_fence
(с 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)

Примечания

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

END_OF_DOCUMENT_MARKER

Обработчики сигналов должны иметь C-связь и, как правило, использовать только функции из общего подмножества C и C++. Однако в общих реализациях допускается использование функции с C++-связью в качестве обработчика сигналов.

Пример

#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

Ссылки

  • Стандарт 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]

Отчёты о дефектах

Следующие отчёты о дефектах, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение, как опубликовано Правильное поведение
LWG 3756 C++17 неясно, является ли std::atomic_flag безопасным для обработки сигналов является

См. также

raise
выполняет обработчик сигнала для определённого сигнала
(функция)
atomic_signal_fence
(C++11)
барьер между потоком и обработчиком сигнала, выполняемым в том же потоке
(функция)
Документация C для signal

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/program/signal

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API