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

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

引用C11标准7.14.1.1.7

“在multithreading程序中使用此函数会导致未定义的行为。实现的行为就像没有库函数调用信号函数一样。”

对此有何解释?

以下代码不言而喻。

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

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

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

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

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

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

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

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


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

我认为你只是错误地表达了未定义行为这个术语,不幸的是,这个行为很重载意味着“坏事会发生”。 这里的术语实际上只是意味着它:C标准没有对在multithreading环境中使用signal意味着什么做出任何假设。

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

所以对于signal和威胁之间的互动并不能给你一份合同。 或者另外说明, signal和线程的交互留给平台实现。