2

我想知道是否有一种简单的方法可以在不使用中间体 signal_handlers 的情况下捕获崩溃的线程的 id

我有以下代码

void signal_handler(int signal)
{
  std::cout << "Caught the signal:" << signal << std::endl;
}

void    handler_t1(int signal)
{
  std::signal(SIGSEGV, signal_handler);
  std::cout << "Thread 1 have received the signal: " << signal << std::endl;
  std::raise(SIGSEGV);
}

void    f1()
{
  std::signal(SIGSEGV, handler_t1);
  std::cout << "Begin thread 1" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(1));
  std::raise(SIGSEGV);
  std::cout << "end thread1" << std::endl;
}

void    f2()
{
  std::cout << "Begin thread 2" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(3));
  std::cout << "end thread2" << std::endl;
}

int     main()
{
  std::thread t1(f1);
  std::thread t2(f2);

  t1.join();
  t2.join();
}

所以我得到

Begin thread 1Begin thread 2
Thread 1 have received the signal: 11
Caught the signal:11
end thread1
end thread2

但是如果我有 5 个线程,我可以避免创建 5 个处理程序吗?

编辑我的包含是

#include <thread>
#include <chrono>
#include <iostream>
#include <csignal>

编辑 我想我看起来像我找到的东西https://stackoverflow.com/a/16259324/2380470 但由于这个东西还不存在,我必须找到别的东西

4

2 回答 2

4

您的问题的答案是“否”。您可以控制软件中断异步执行的线程(通过阻塞特定线程中的信号);在 POSIX 平台上,您可以阻止所有线程中信号的异步执行,而是使用 sigwait() 在专用线程中响应信号。但是如果中断是通过调用 kill() 或者是系统生成的中断(例如 SIGSEGV)而发生的,POSIX 中没有标准的方法可以在信号处理程序中确定哪个线程生成了信号。

请注意,线程不会“抛出”信号。另请注意,这些都与 C++ 标准无关。

编辑我注意到您的一位评论者可能会假设信号处理程序在生成信号的线程中执行。除了在调用 raise() 的情况下,情况并非如此。由 kill() 产生的信号或系统生成的信号可以在没有阻塞该信号的任何线程中异步执行。如果多个线程的信号被解除阻塞,则不确定哪个线程被中断(这是系统及其调度程序的选择)。另请注意,在用户生成中断的情况下,在 POSIX 中可以调用 sigqueue() 而不是 kill(),并且 sigqueue 可以传入一个用户数据值,该值可以识别调用者的身份。然而,这显然与 SIGSEGV 无关。在 POSIX 中,使用 pthread_kill() 您还可以使信号中断进行调用的进程中的特定线程(但这不能识别调用者,也与 SIGSEGV 无关)。多线程程序中的 raise() 具有调用 pthread_kill() 的效果(它将在调用 raise() 的线程中执行:但 raise() 对于信息传递的目的是无用的)。

于 2013-07-24T18:09:34.590 回答
2

gettid() 将为您提供调用它的线程的 ID。这会给你你想要的!

http://linux.die.net/man/2/gettid

如果您也将线程存储在某种线程缓冲区中,您总是可以根据它们在数组中的位置自己标记它们(例如线程 0 -> n 用于线程 [n])

于 2013-07-24T14:30:17.503 回答