简体   繁体   中英

Are std::signal and std::raise thread-safe?

The C and C++ standards support the concept of signal. However, the C11 standard says that the function signal() cannot be called in multi-threaded environments, or the behavior is undefined. But I think the signal mechanism is by nature for multi-threaded environments.

A quote from the C11 standard 7.14.1.1.7

"Use of this function in a multi-threaded program results in undefined behavior. The implementation shall behave as if no library function calls the signal function."

Any explanations about this?

The following code is self-evident.

#include <thread>
#include <csignal>

using namespace std;

void SignalHandler(int)
{
    // Which thread context here?
}

void f()
{
    //
    // Running in another thread context.
    //
    raise(SIGINT); // Is this call safe?
}

int main()
{
    //
    // Register the signal handler in main thread context.
    //
    signal(SIGINT, SignalHandler);

    thread(f).join();
}

But I think the signal mechanism is by nature for multi-threaded environments.

I think this sentence is the central misunderstanding. signal() is a method for inter- process communication, not for inter- thread . Threads share common memory and can therefore communicate via mutexes and control structures. Processes don't have common memory and must make-do with some explicit communication structures like signal() or the filesystem.

I think you're confusing signaling, which is process specific, with communication between threads. If it is sharing information between threads that you're after, you will probably find what you want in the new C++11 thread support library . Of course, it depends on what you really want to do.

From what I can tell of your code, you want a thread to "signal" an event in some way and you want to be able to run some code when that event is signalled. Given that, I'd take a closer look at the Futures section in the thread support library.

The C11 standard's statement that "Use of this function in a multi-threaded program results in undefined behavior," refers specifically to the function signal() . So the question is if the use of signal() is done "in a multi-threaded program."

The term 'multi-threaded program' isn't defined in the C standard as far as I can tell, but I would take it to mean a program in which multiple threads of execution have been created and have not completed. That would mean that at the time signal() is called in your example program the program is not multi-threaded and therefore the program's behavior is not undefined under this requirement.

(However C++11 requires that "All signal handlers shall have C linkage," [18.10 Other runtime support [support.runtime] p9] . Since your example program uses a handler with C++ linkage the behavior is undefined.)


As others have pointed out signals aren't intended for communication between threads. For example the C and C++ standards don't even specify what thread they run on. The standard library instead provides other tools for inter-thread communcation, such as mutexes, atomics, etc.

I think you just misintrepret the term undefined behavior , which is unfortunately much overloaded to mean "bad things will happen". Here the term really just means what it says: the C standard doesn't make any assumption about what it means to use signal in a multi-threaded context.

In general the signal / raise interface in the C standard is not very useful by itself, but only a placeholder for platform/OS specific things that are defined on top of it.

So for an interaction between signal and threats doesn't give you a contract. Or stated otherwise, the interaction of signal and threads is left to the platform implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM