多线程和捕获信号

问题描述 投票:0回答:1

我已经阅读了其他答案,信号被传递到任意线程;然而,根据我自己的测试:

#include <iostream>                                                                                                                                                                                                             
#include <thread>                                                                                                                                                                                                               
#include <vector>                                                                                                                                                                                                               
#include <chrono>                                                                                                                                                                                                               
                                                                                                                                                                                                                                
void foo(int i) {                                                                                                                                                                                                               
  while (true) {                                                                                                                                                                                                                
    std::cout << i << std::endl;                                                                                                                                                                                                
    std::this_thread::sleep_for(std::chrono::seconds(1));                                                                                                                                                                       
  }                                                                                                                                                                                                                             
}                                                                                                                                                                                                                               
int main() {                                                                                                                                                                                                                    
  std::vector<std::thread> t;                                                                                                                                                                                                   
  for (int i = 0 ; i < 5 ; i++) {                                                                                                                                                                                               
    t.emplace_back([=] {                                                                                                                                                                                                        
      foo(i);                                                                                                                                                                                                                   
    });                                                                                                                                                                                                                         
  }                                                                                                                                                                                                                             
  for (auto& v : t)                                                                                                                                                                                                             
    v.join();                                                                                                                                                                                                                   
}                                                                                                                                                                                                                               

我决定了三件事:

  • 如果我不这样做
    detach
    join
    ,我会从
    libc++abi
  • 中止
  • 如果我
    detach
    每个线程在产生时,我会立即退出并看不到输出
  • 如果我
    join
    ,就会出现预期的行为,但是信号会杀死所有线程

有人可以解释一下这些行为吗?我主要关心的是让所有线程在接收到信号时退出(使用尽可能少的代码),但这些行为对我来说很好奇。

我对每一个的想法是:

  • 潜在的未定义行为
  • main
    退出会杀死所有线程(这让我觉得很奇怪)
  • 最后一个非常出乎意料,因为我认为信号被传递到随机线程并且只会杀死该线程
c++ multithreading unix
1个回答
0
投票

项目符号 1:

  • 如果我不分离或加入,我会从 libc++abi 中止

我猜你的意思是:

libc++abi: terminating

这也是我得到的。

main
返回时,
~vector<thread>()
会运行
t
,从而破坏每个
thread
~thread()
的规格是
:

效果: 如果

joinable()
,则调用
terminate
([ except.terminate])。否则没有效果。

A

thread
joinable()
是其
get_id()
成员函数不返回默认构造的
thread​::​id
。 如果已构造
thread
来运行函数但未加入或分离,则会发生这种情况。

因此,在

thread
的析构函数中被破坏的第一个
t
调用
terminate
并结束进程。 当进程结束时,仍在运行的线程接触已破坏的对象将调用未定义的行为。 如果他们设法避免这种情况,当控制权交还给操作系统时,他们就会消失。

项目符号 2:

  • 如果我在生成每个线程时将其分离,我会立即退出并看不到任何输出

当执行从 main 末尾流出时,

exit(0)
被隐式调用。 规格:

如果控制从

main
复合语句的末尾流出,则效果相当于操作数为 0 的返回(另请参见 [ except.handle ])。

如果分离的线程在对象被破坏后接触该对象,那么您会得到未定义的行为。 如果分离的线程设法避免这种情况,那么当进程将控制权交回主机系统时,它就会消失。

项目符号 3:

  • 如果我加入,就会出现预期的行为,但是信号会杀死所有线程

join()
将导致
main()
永远等待,因为线程处于无限循环中。 没有线程退出,因此
join()
永远不会返回。

Control-C 向任何线程发送

SIGINT
(可能包括
main()
)。 默认行为是接收信号的线程终止整个进程。 与前两个要点一样,如果仍在运行的线程设法通过不接触已破坏的对象来避免未定义的行为,那么当控制权交还给操作系统时,它们就会消失。

有趣的事实:

cout
永远不会被破坏,但当控制权交还给操作系统时当然会消失。

© www.soinside.com 2019 - 2024. All rights reserved.