Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/program/signal"

From cppreference.com
< cpp‎ | utility‎ | program
m (References: +C++20 ref too)
(Link update.)
 
(8 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{cpp/title| signal}}
+
{{cpp/title|signal}}
 
{{cpp/utility/program/navbar}}
 
{{cpp/utility/program/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | csignal}}
+
{{dcl header|csignal}}
{{dcl |num=1|
+
{{dcl|num=1|
/*signal-handler*/* signal(int sig, /*signal-handler*/* handler);
+
/* signal-handler */* signal( int sig, /* signal-handler */* handler );
 
}}
 
}}
{{dcl |num=2|1=
+
{{dcl|num=2|notes={{mark expos}}|1=
extern "C" using /*signal-handler*/ = void(int); // exposition-only
+
extern "C" using /* signal-handler */ = void(int);
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Sets the handler for signal {{tt|sig}}. The signal handler can be set so that default handling will occur, signal is ignored, or a user-defined function is called.
+
Changes handling of the signal {{c|sig}}. Depending on {{c|handler}}, the signal can be ignored, set to default, or handled by a user-defined function.
  
 
<!--C11's 7.14.1p3-->When signal handler is set to a function and a signal occurs, it is implementation defined whether {{c|std::signal(sig, SIG_DFL)}} will be executed immediately before the start of signal handler. Also, the implementation can prevent some implementation-defined set of signals from occurring while the signal handler runs.  
 
<!--C11's 7.14.1p3-->When signal handler is set to a function and a signal occurs, it is implementation defined whether {{c|std::signal(sig, SIG_DFL)}} will be executed immediately before the start of signal handler. Also, the implementation can prevent some implementation-defined set of signals from occurring while the signal handler runs.  
Line 17: Line 17:
 
For some of the signals, the implementation may call {{c|std::signal(sig, SIG_IGN)}} at the startup of the program. For the rest, the implementation must call {{c|std::signal(sig, SIG_DFL)}}.
 
For some of the signals, the implementation may call {{c|std::signal(sig, SIG_IGN)}} at the startup of the program. For the rest, the implementation must call {{c|std::signal(sig, SIG_DFL)}}.
  
(Note: POSIX introduced [http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html {{tt|sigaction}}] to standardize these implementation-defined behaviors)
+
(Note: POSIX introduced [https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html {{tt|sigaction}}] to standardize these implementation-defined behaviors)
  
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | sig | the signal to set the signal handler to. It can be an implementation-defined value or one of the following values:  
+
{{par|sig|the signal to set the signal handler to. It can be an implementation-defined value or one of the following values:  
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/utility/program/dsc SIG_types}}
+
{{dsc inc|cpp/utility/program/dsc SIG_types}}
{{dsc end}} }}
+
{{dsc end}}}}
{{par | handler | the signal handler. This must be one of the following:  
+
{{par|handler|the signal handler. This must be one of the following:  
*{{lc|SIG_DFL}} macro. The signal handler is set to default signal handler.
+
* {{lc|SIG_DFL}} macro. The signal handler is set to default signal handler.
*{{lc|SIG_IGN}} macro. The signal is ignored.
+
* {{lc|SIG_IGN}} macro. The signal is ignored.
*pointer to a function. The signature of the function must be equivalent to the following:
+
* A pointer to a function. The signature of the function must be equivalent to the following:
{{ddcl |  
+
{{ddcl|extern "C" void fun(int sig);}}
extern "C" void fun(int sig);}}}}
+
}}
 
{{par end}}
 
{{par end}}
  
Line 39: Line 39:
 
The following limitations are imposed on the user-defined function that is installed as a signal handler.
 
The following limitations are imposed on the user-defined function that is installed as a signal handler.
  
{{cpp/rev
+
{{rev begin}}
|until c++17=
+
{{rev|until=c++17|
 
If the signal handler is called NOT as a result of {{lc|std::abort}} or {{lc|std::raise}} (asynchronous signal), the behavior is undefined if
 
If the signal handler is called NOT as a result of {{lc|std::abort}} or {{lc|std::raise}} (asynchronous signal), the behavior is undefined if
 
* the signal handler calls any function within the standard library, except
 
* the signal handler calls any function within the standard library, except
Line 46: Line 46:
 
:* {{lc|std::_Exit}}
 
:* {{lc|std::_Exit}}
 
:* {{lc|std::quick_exit}}
 
:* {{lc|std::quick_exit}}
:* {{c|std::signal}} with the first argument being the number of the signal currently handled (async handler can re-register itself, but not other signals).  
+
:* {{tt|std::signal}} with the first argument being the number of the signal currently handled (async handler can re-register itself, but not other signals).  
* the signal handler refers to any object with static storage duration that is not {{lc|std::atomic}}{{mark since c++11}} or {{c|volatile std::sig_atomic_t}}.
+
* the signal handler refers to any object with static storage duration that is not {{rev inl|since=c++11|{{lc|std::atomic}} or }}{{c/core|volatile std::sig_atomic_t}}.
|since c++17=
+
}}
 +
{{rev|since=c++17|
 +
A ''plain lock-free atomic operation'' is an invocation of a function {{c|f}} from {{header|atomic}}{{rev inl|since=c++23| or {{header|stdatomic.h}}}}, such that:
 +
* {{c|f}} is the function {{lc|std::atomic_is_lock_free}},
 +
* {{c|f}} is the member function {{tt|is_lock_free}} (e.g. {{l2tf std|cpp/atomic/atomic/is_lock_free}}),
 +
* {{c|f}} is a non-static member function of {{lc|std::atomic_flag}},
 +
* {{c|f}} is a non-member function, and the first parameter of {{c|f}} has type ''cv'' {{c/core|std::atomic_flag*}},
 +
* {{c|f}} is a non-static member function invoked on an object {{c|obj}}, such that {{c|obj.is_lock_free()}} yields {{c|true}}, or
 +
* {{c|f}} is a non-member function, and for every pointer-to-atomic argument {{c|arg}} passed to {{c|f}}, {{c|std::atomic_is_lock_free(arg)}} yields {{c|true}}.
 +
 
 
The behavior is undefined if any signal handler performs any of the following:
 
The behavior is undefined if any signal handler performs any of the following:
* call to any library function, except the following ''signal-safe'' functions (note, in particular, dynamic allocation is not signal-safe):
+
* call to any library function, except for plain lock-free atomic operations and the following ''signal-safe'' functions (note, in particular, dynamic allocation is not signal-safe):
:* members functions of {{lc|std::atomic}} and non-member functions from {{header|atomic}} if the atomic type they operate on is lock-free. The functions {{lc|std::atomic_is_lock_free}} and {{lc|std::atomic::is_lock_free}} are signal-safe for any atomic type.
+
:* {{tt|std::signal}} with the first argument being the number of the signal currently handled (signal handler can re-register itself, but not other signals).
:* {{c|std::signal}} with the first argument being the number of the signal currently handled (signal handler can re-register itself, but not other signals).
+
 
:* member functions of {{lc|std::numeric_limits}}
 
:* member functions of {{lc|std::numeric_limits}}
 
:* {{lc|std::_Exit}}
 
:* {{lc|std::_Exit}}
Line 64: Line 72:
 
* a {{ltt|cpp/language/dynamic_cast}} expression
 
* a {{ltt|cpp/language/dynamic_cast}} expression
 
* a {{ltt|cpp/language/throw}} expression
 
* a {{ltt|cpp/language/throw}} expression
* entry to a {{ltt|cpp/language/try_catch|try}} block, including [[cpp/language/function-try-block|function-{{tt|try}}-block]]
+
* entry to a {{ltt|cpp/language/try|{{c/core|try}} block}}
* initialization of a static variable that performs [[cpp/language/initialization#Non-local_variables|dynamic non-local initialization]] (including delayed until first ODR-use)
+
* initialization of a static variable that performs [[cpp/language/initialization#Non-local variables|dynamic non-local initialization]] (including delayed until first ODR-use)
 
* waits for completion of initialization of any variable with static storage duration due to another thread concurrently initializing it
 
* waits for completion of initialization of any variable with static storage duration due to another thread concurrently initializing it
 
}}
 
}}
 +
{{rev end}}
  
 
<!--C11's 7.14.1p3-->If the user defined function returns when handling {{lc|SIGFPE}}, {{lc|SIGILL}}, {{lc|SIGSEGV}} or any other implementation-defined signal specifying a computational exception, the behavior is undefined.
 
<!--C11's 7.14.1p3-->If the user defined function returns when handling {{lc|SIGFPE}}, {{lc|SIGILL}}, {{lc|SIGSEGV}} or any other implementation-defined signal specifying a computational exception, the behavior is undefined.
Line 73: Line 82:
 
<!--C11's 7.14.1p4-->If the signal handler is called as a result of {{lc|std::abort}} or {{lc|std::raise}} (synchronous signal), the behavior is undefined if the signal handler calls {{lc|std::raise}}.
 
<!--C11's 7.14.1p4-->If the signal handler is called as a result of {{lc|std::abort}} or {{lc|std::raise}} (synchronous signal), the behavior is undefined if the signal handler calls {{lc|std::raise}}.
  
{{cpp/rev
+
{{rev begin}}
|until c++14=
+
{{rev|until=c++14|
 
<!--C++11 [intro.execution]p6, C11 5.1.2.3p5-->On entry to the signal handler, the state of the [[cpp/numeric/fenv|floating-point environment]] and the values of all objects is unspecified, except for
 
<!--C++11 [intro.execution]p6, C11 5.1.2.3p5-->On entry to the signal handler, the state of the [[cpp/numeric/fenv|floating-point environment]] and the values of all objects is unspecified, except for
* objects of type {{c|volatile std::sig_atomic_t}}
+
* objects of type {{c/core|volatile std::sig_atomic_t}}
* objects of lock-free {{lc|std::atomic}} types {{mark since c++11}}
+
{{rrev|since=c++11|
<!--[atomics.fences]p6-->* side effects made visible through {{lc|std::atomic_signal_fence}} {{mark since c++11}}
+
* objects of lock-free {{lc|std::atomic}} types
 +
<!--[atomics.fences]p6-->* side effects made visible through {{lc|std::atomic_signal_fence}} }}
  
On return from a signal handler, the value of any object modified by the signal handler that is not {{c|volatile std::sig_atomic_t}} or lock-free {{lc|std::atomic}} is indeterminate.
+
On return from a signal handler, the value of any object modified by the signal handler that is not {{c/core|volatile std::sig_atomic_t}} or lock-free {{lc|std::atomic}} is indeterminate.
|since c++14=
+
}}
 +
{{rev|since=c++14|
 
A call to the function {{tt|signal()}} [[cpp/atomic/memory_order|synchronizes-with]] any resulting invocation of the signal handler.
 
A call to the function {{tt|signal()}} [[cpp/atomic/memory_order|synchronizes-with]] any resulting invocation of the signal handler.
  
 
If a signal handler is executed as a result of a call to {{lc|std::raise}} (synchronously), then the execution of the handler is ''sequenced-after'' the invocation of {{tt|std::raise}} and ''sequenced-before'' the return from it and runs on the same thread as {{lc||std::raise}}. Execution of the handlers for other signals is ''unsequenced'' with respect to the rest of the program and runs on an unspecified thread.
 
If a signal handler is executed as a result of a call to {{lc|std::raise}} (synchronously), then the execution of the handler is ''sequenced-after'' the invocation of {{tt|std::raise}} and ''sequenced-before'' the return from it and runs on the same thread as {{lc||std::raise}}. Execution of the handlers for other signals is ''unsequenced'' with respect to the rest of the program and runs on an unspecified thread.
  
Two accesses to the same object of type {{c|volatile std::sig_atomic_t}} do not result in a data race if both occur in the same thread, even if one or more occurs in a signal handler.  
+
Two accesses to the same object of type {{c/core|volatile std::sig_atomic_t}} do not result in a data race if both occur in the same thread, even if one or more occurs in a signal handler.  
For each signal handler invocation, evaluations performed by the thread invoking a signal handler can be divided into two groups A and B, such that no evaluations in B ''happen-before'' evaluations in A, and the evaluations of such {{c|volatile std::sig_atomic_t}} objects take values as though all evaluations in A [[cpp/atomic/memory_order|happened-before]] the execution of the signal handler and the execution of the signal handler ''happened-before'' all evaluations in B.
+
For each signal handler invocation, evaluations performed by the thread invoking a signal handler can be divided into two groups A and B, such that no evaluations in B ''happen-before'' evaluations in A, and the evaluations of such {{c/core|volatile std::sig_atomic_t}} objects take values as though all evaluations in A [[cpp/atomic/memory_order|happened-before]] the execution of the signal handler and the execution of the signal handler ''happened-before'' all evaluations in B.
 
}}
 
}}
 +
{{rev end}}
  
 
===Notes===
 
===Notes===
POSIX requires that {{tt|signal}} is thread-safe, and [http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 specifies a list of async-signal-safe library functions] that may be called from any signal handler.
+
POSIX requires that {{tt|signal}} is thread-safe, and [https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 specifies a list of async-signal-safe library functions] that may be called from any signal handler.
  
{{cpp/rev
+
Signal handlers are expected to have [[cpp/language/language_linkage|C linkage]] and, in general, only use the features from the common subset of C and C++. However, common implementations allow a function with C++ linkage to be used as a signal handler.
|until c++17=
+
Signal handlers are expected to have [[cpp/language/language_linkage|C linkage]] and, in general, only use the features from the common subset of C and C++. It is implementation-defined if a function with C++ linkage can be used as a signal handler. <!-- per C++11 $18.10[support.runtime]/9. Note: this was removed in C++17 -->
+
|since c++17=
+
There is no restriction on the linkage of signal handlers.
+
}}
+
  
 
===Example===
 
===Example===
 
{{example
 
{{example
|
+
|
| p=true
+
|code=
| code=
+
 
#include <csignal>
 
#include <csignal>
 
#include <iostream>
 
#include <iostream>
Line 110: Line 116:
 
namespace
 
namespace
 
{
 
{
  volatile std::sig_atomic_t gSignalStatus;
+
    volatile std::sig_atomic_t gSignalStatus;
 
}
 
}
  
 
void signal_handler(int signal)
 
void signal_handler(int signal)
 
{
 
{
  gSignalStatus = signal;
+
    gSignalStatus = signal;
 
}
 
}
  
 
int main()
 
int main()
 
{
 
{
  // Install a signal handler
+
    // Install a signal handler
  std::signal(SIGINT, signal_handler);
+
    std::signal(SIGINT, signal_handler);
 
+
   
  std::cout << "SignalValue: " << gSignalStatus << '\n';
+
    std::cout << "SignalValue: " << gSignalStatus << '\n';
  std::cout << "Sending signal: " << SIGINT << '\n';
+
    std::cout << "Sending signal: " << SIGINT << '\n';
  std::raise(SIGINT);
+
    std::raise(SIGINT);
  std::cout << "SignalValue: " << gSignalStatus << '\n';
+
    std::cout << "SignalValue: " << gSignalStatus << '\n';
 
}
 
}
| output=
+
|p=true
 +
|output=
 
SignalValue: 0
 
SignalValue: 0
 
Sending signal: 2
 
Sending signal: 2
Line 135: Line 142:
  
 
===References===
 
===References===
 +
{{ref std c++23}}
 +
{{ref std|section=17.13.5|title=Signal handlers|id=support.signal}}
 +
{{ref std end}}
 
{{ref std c++20}}
 
{{ref std c++20}}
{{ref std | section=17.13.5 | title=Signal handlers | id=support.signal}}
+
{{ref std|section=17.13.5|title=Signal handlers|id=support.signal}}
 
{{ref std end}}
 
{{ref std end}}
 
{{ref std c++17}}
 
{{ref std c++17}}
{{ref std | section=21.10.4 | title=Signal handlers | id=support.signal}}
+
{{ref std|section=21.10.4|title=Signal handlers|id=support.signal}}
 
{{ref std end}}
 
{{ref std end}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|wg=lwg|dr=3756|std=C++17|before=it was unclear whether {{lc|std::atomic_flag}} is signal-safe|after=it is}}
 +
{{dr list end}}
  
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/utility/program/dsc raise}}
+
{{dsc inc|cpp/utility/program/dsc raise}}
{{dsc inc | cpp/atomic/dsc atomic_signal_fence}}
+
{{dsc inc|cpp/atomic/dsc atomic_signal_fence}}
{{dsc see c | c/program/signal}}
+
{{dsc see c|c/program/signal}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 01:15, 5 June 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
 
Defined in header <csignal>
/* signal-handler */* signal( int sig, /* signal-handler */* handler );
(1)
extern "C" using /* signal-handler */ = void(int);
(2) (exposition only*)

Changes handling of the signal sig. Depending on handler, the signal can be ignored, set to default, or handled by a user-defined function.

When signal handler is set to a function and a signal occurs, it is implementation defined whether std::signal(sig, SIG_DFL) will be executed immediately before the start of signal handler. Also, the implementation can prevent some implementation-defined set of signals from occurring while the signal handler runs.

For some of the signals, the implementation may call std::signal(sig, SIG_IGN) at the startup of the program. For the rest, the implementation must call std::signal(sig, SIG_DFL).

(Note: POSIX introduced sigaction to standardize these implementation-defined behaviors)

Contents

[edit] Parameters

sig - the signal to set the signal handler to. It can be an implementation-defined value or one of the following values:
defines signal types
(macro constant) [edit]
handler - the signal handler. This must be one of the following:
  • SIG_DFL macro. The signal handler is set to default signal handler.
  • SIG_IGN macro. The signal is ignored.
  • A pointer to a function. The signature of the function must be equivalent to the following:
extern "C" void fun(int sig);


[edit] Return value

Previous signal handler on success or SIG_ERR on failure (setting a signal handler can be disabled on some implementations).

[edit] Signal handler

The following limitations are imposed on the user-defined function that is installed as a signal handler.

If the signal handler is called NOT as a result of std::abort or std::raise (asynchronous signal), the behavior is undefined if

  • the signal handler calls any function within the standard library, except
  • std::abort
  • std::_Exit
  • std::quick_exit
  • std::signal with the first argument being the number of the signal currently handled (async handler can re-register itself, but not other signals).
(until C++17)

A plain lock-free atomic operation is an invocation of a function f from <atomic> or <stdatomic.h>(since C++23), such that:

The behavior is undefined if any signal handler performs any of the following:

  • call to any library function, except for plain lock-free atomic operations and the following signal-safe functions (note, in particular, dynamic allocation is not signal-safe):
  • access to an object with thread storage duration
  • a dynamic_cast expression
  • a throw expression
  • entry to a try block
  • initialization of a static variable that performs dynamic non-local initialization (including delayed until first ODR-use)
  • waits for completion of initialization of any variable with static storage duration due to another thread concurrently initializing it
(since C++17)

If the user defined function returns when handling SIGFPE, SIGILL, SIGSEGV or any other implementation-defined signal specifying a computational exception, the behavior is undefined.

If the signal handler is called as a result of std::abort or std::raise (synchronous signal), the behavior is undefined if the signal handler calls std::raise.

On entry to the signal handler, the state of the floating-point environment and the values of all objects is unspecified, except for

(since C++11)

On return from a signal handler, the value of any object modified by the signal handler that is not volatile std::sig_atomic_t or lock-free std::atomic is indeterminate.

(until C++14)

A call to the function signal() synchronizes-with any resulting invocation of the signal handler.

If a signal handler is executed as a result of a call to std::raise (synchronously), then the execution of the handler is sequenced-after the invocation of std::raise and sequenced-before the return from it and runs on the same thread as std::raise. Execution of the handlers for other signals is unsequenced with respect to the rest of the program and runs on an unspecified thread.

Two accesses to the same object of type volatile std::sig_atomic_t do not result in a data race if both occur in the same thread, even if one or more occurs in a signal handler. For each signal handler invocation, evaluations performed by the thread invoking a signal handler can be divided into two groups A and B, such that no evaluations in B happen-before evaluations in A, and the evaluations of such volatile std::sig_atomic_t objects take values as though all evaluations in A happened-before the execution of the signal handler and the execution of the signal handler happened-before all evaluations in B.

(since C++14)

[edit] Notes

POSIX requires that signal is thread-safe, and specifies a list of async-signal-safe library functions that may be called from any signal handler.

Signal handlers are expected to have C linkage and, in general, only use the features from the common subset of C and C++. However, common implementations allow a function with C++ linkage to be used as a signal handler.

[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';
}

Possible output:

SignalValue: 0
Sending signal: 2
SignalValue: 2

[edit] References

  • C++23 standard (ISO/IEC 14882:2024):
  • 17.13.5 Signal handlers [support.signal]
  • C++20 standard (ISO/IEC 14882:2020):
  • 17.13.5 Signal handlers [support.signal]
  • C++17 standard (ISO/IEC 14882:2017):
  • 21.10.4 Signal handlers [support.signal]

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 3756 C++17 it was unclear whether std::atomic_flag is signal-safe it is

[edit] See also

runs the signal handler for particular signal
(function) [edit]
fence between a thread and a signal handler executed in the same thread
(function) [edit]
C documentation for signal