是std :: signal和std :: raise线程安全吗?

时间:2013-01-30 20:45:09

标签: c++ c multithreading c++11 signals

C和C ++标准支持信号的概念。但是,C11标准表示无法在多线程环境中调用函数signal(),或者行为未定义。但我认为信号机制本质上适用于多线程环境。

C11标准7.14.1.1.7的引用

  

“在多线程程序中使用此函数会导致未定义的行为   实现应该表现得好像没有库函数调用信号函数。“

对此有何解释?

以下代码不言而喻。

#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();
}

4 个答案:

答案 0 :(得分:16)

  

但我认为信号机制本质上适用于多线程环境。

我认为这句话是中心的误解。 signal()是一种进行进程通信的方法,而不是用于线程的方法。线程共享公共内存,因此可以通过互斥锁和控制结构进行通信。进程没有公共内存,必须使用某些显式通信结构(如signal()或文件系统)进行处理。

答案 1 :(得分:4)

我认为你混淆信号,这是特定于流程的,线程之间的通信。如果它是您之后的线程之间共享信息,您可能会在新的C++11 thread support library中找到您想要的内容。当然,这取决于你真正想做的事情。

从我所知道的代码中,您希望线程以某种方式“发出信号”事件,并且您希望能够在发出该事件信号时运行一些代码。鉴于此,我将仔细研究线程支持库中的Futures部分。

答案 2 :(得分:2)

C11标准的声明“在多线程程序中使用此函数会导致未定义的行为”,特指函数signal()。所以问题是如果在多线程程序中使用signal()。“

就我所知,术语“多线程程序”在C标准中没有定义,但我认为这意味着一个程序,其中已经创建了多个执行线程但尚未完成。这意味着在您的示例程序中调用signal()时,程序不是多线程的,因此在此要求下程序的行为不是未定义的。

(但是C ++ 11要求“所有信号处理程序都应具有C链接”, [18.10其他运行时支持[support.runtime] p9] 。因为您的示例程序使用带有C ++的处理程序联系行为未定义。)


正如其他人所指出的那样,信号不是用于线程之间的通信。例如,C和C ++标准甚至没有指定它们运行的​​线程。标准库提供了其他用于线程间通信的工具,例如互斥,原子等。

答案 3 :(得分:1)

我认为你只是错误地表达了未定义的行为一词,不幸的是,这意味着很多重载意味着&#34;坏事将会发生&#34;。这里的术语实际上只是意味着它:C标准没有假设在多线程环境中使用signal意味着什么。

通常,C标准中的signal / raise接口本身并不是非常有用,但只是在其上定义的平台/操作系统特定事物的占位符。

因此signal与威胁之间的互动并不能给你一份合同。或者另有说明,signal和线程的交互留给平台 实施