获取抛出信号的线程的id

时间:2013-07-24 14:29:08

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

我想知道是否有一种简单的方法可以在不使用中间信号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 但由于这个东西还不存在,我必须找到别的东西

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:2)

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

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

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