std::signal
Определено в заголовочном файле <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_ERR в случае ошибки (установка обработчиков сигналов может быть отключена на некоторых реализациях)
[править] Обработчик сигнала
На пользовательскую функцию, устанавливаемую в качестве обработчика сигнала, накладываются следующие ограничения.
Если обработчик сигнала вызывается НЕ в результате std::abort или std::raise (асинхронный сигнал), поведение не определено, если
|
(до C++17) |
Простая атомарная операция без блокировок это вызов функции f из <atomic> или <stdatomic.h> (начиная с C++23), так что:
Поведение не определено, если какой-либо обработчик сигнала выполняет одно из следующих действий:
|
(начиная с C++17) |
Если пользовательская функция выполнила возврат, когда случился сигнал SIGFPE, SIGILL, SIGSEGV или любой другой определённый реализацией сигнал, определяющий ошибку вычисления, то поведение будет не определено.
Если обработчик сигнала вызван в результате вызова std::abort или std::raise (синхронный сигнал), то поведение будет не определённым, если обработчик сигнала вызовет std::raise.
При входе в обработчик сигнала состояние среды с плавающей запятой и значения всех объектов не указаны, за исключением
При возврате из обработчика сигнала значение любого объекта, изменённого обработчиком сигнала, который не является volatile std::sig_atomic_t или неблокируемым std::atomic, является неопределённым. |
(до C++14) | ||
Вызов функции Если обработчик сигнала выполняется в результате вызова std::raise (синхронно), то выполнение обработчика последовательно после вызова Два обращения к одному и тому же объекту типа volatile std::sig_atomic_t не приводят к гонке данных, если оба они происходят в одном и том же потоке, даже если один или несколько из них происходят в обработчике сигнала. Для каждого вызова обработчика сигнала оценки, выполняемые потоком, вызывающим обработчик сигнала, могут быть разделены на две группы A и B, так что никакие оценки в B не происходят до оценок в A, и оценки таких объектов volatile std::sig_atomic_t принимают значения, как если бы все вычисления в A произошли до выполнения обработчика сигнала и выполнение обработчика сигнала произошло до всех оценок в B. |
(начиная с C++14) |
[править] Примечание
POSIX требует, чтобы signal
был потокобезопасным, и определяется список потокобезопасных асинхронных библиотечных функций, которые могут быть вызваны из любого обработчика сигнала.
Обработчики сигнала должны иметь связывание С, и, как правило, использовать только функции из общего подмножества C и C++. Возможность функции со связыванием C++ использоваться в качестве обработчика сигнала определяется реализацией. |
(до C++17) |
Нет никаких ограничений на связывание обработчиков сигналов. |
(начиная с C++17) |
[править] Пример
#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 << "Значение сигнала: " << gSignalStatus << '\n'; std::cout << "Отправка сигнала: " << SIGINT << '\n'; std::raise(SIGINT); std::cout << "Значение сигнала: " << gSignalStatus << '\n'; }
Возможный вывод:
Значение сигнала: 0 Отправка сигнала: 2 Значение сигнала: 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++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 3756 | C++17 | было неясно, безопасен ли std::atomic_flag для сигналов | безопасен |
[править] Смотрите также
выполняет обработчик для конкретного сигнала (функция) | |
(C++11) |
барьер между потоком и обработчиком сигнала, выполняемым в этом же потоке (функция) |
Документация C по signal
|